在前后端分离开发中,本地前端一般通过 http://localhost:3000、http://localhost:5173、http://localhost:8080 等地址运行,而后端接口常常部署在:
https://api.example.com由于协议、域名或端口不同,浏览器会触发 CORS(跨域访问限制),导致接口请求报错,例如:
Access to fetch at 'https://api.example.com' from origin 'http://localhost:5173' has been blocked by CORS policy要解决这个问题,我们可以在 Nginx 中为开发环境添加 跨域支持。
✅ 正确理解:CORS 不允许写多个域名
错误写法(无效):
add_header Access-Control-Allow-Origin http://localhost:5173, http://localhost:3000;浏览器会直接忽略,因为 Access-Control-Allow-Origin 必须只能有一个值。
✅ 最佳实践:根据请求的 Origin 动态返回允许的来源
我们可以让 Nginx 判断请求的 Origin 是否在允许范围内,如果是,就把它回传给浏览器,解决跨域问题。
📦 完整可直接复制的 Nginx 配置
# 开发环境 API 代理
server {
listen 443 ssl;
server_name api.example.com;
# SSL 略...
location / {
# 允许所有 localhost 端口
if ($http_origin ~* "^https?://localhost(:\d+)?$") {
add_header Access-Control-Allow-Origin $http_origin;
add_header Access-Control-Allow-Credentials true;
}
# 预检请求处理
if ($request_method = OPTIONS) {
add_header Access-Control-Allow-Methods "GET, POST, PUT, DELETE, OPTIONS";
add_header Access-Control-Allow-Headers "Content-Type, Authorization, X-Requested-With";
return 204;
}
proxy_pass http://backend_service; # 你的后端服务地址
}
}🧠 这段配置做了哪些事?
| 功能 | 说明 |
|---|---|
动态匹配 Origin | 只允许 http://localhost:* 发请求 |
| 支持携带 Cookie / Token | Access-Control-Allow-Credentials: true |
| 支持预检(OPTIONS)请求 | 防止跨域被浏览器拦截 |
| 不影响生产环境 | 可只在开发环境使用 |
✅ 前端使用时记得加 withCredentials(如果你传 Cookie)
fetch("https://api.example.com/user/info", {
credentials: "include"
});如果你用 axios:
axios.defaults.withCredentials = true;🔒 安全提示(非常重要)
- 仅在开发环境允许
$http_origin - 生产环境一定要写死域名,例如:
add_header Access-Control-Allow-Origin https://www.yourwebsite.com;否则会有 安全风险。
🎯 总结
| 场景 | 解决方案 |
|---|---|
| 本地开发跨域 | 使用 $http_origin 动态回源 |
| 不同端口需要访问接口 | 正则匹配 localhost |
| 正式环境 | 固定域名,禁止动态 CORS |