Nginx跨域配置核心是精准注入合法CORS响应头:必须同时设置Access-Control-Allow-Origin(禁用*)、-Methods、-Headers、-Credentials(与Origin共存)、-Max-Age,并对OPTIONS预检返回204且补全全部CORS头。

直接在 Nginx 中用 add_header 配置 CORS,核心是让浏览器收到的响应里包含合法、完整且时机正确的跨域头。它不修改请求,只补全响应头;不能靠后端配合,也不依赖前端改代码——Nginx 在代理层统一拦截并注入即可生效。
必须配全的基础响应头
仅写 Access-Control-Allow-Origin 是不够的,漏掉任意一项都可能被浏览器拒绝:
-
Access-Control-Allow-Origin:设为具体域名(如
https://your-app.com)更安全;若需带 Cookie,严禁用* -
Access-Control-Allow-Methods:列出真实会用到的方法,如
GET, POST, PUT, DELETE, OPTIONS -
Access-Control-Allow-Headers:前端发了哪些自定义头(如
X-User-ID、Authorization),就必须列全,大小写要一致 -
Access-Control-Allow-Credentials:设为
true才能传 Cookie,此时Origin必须是明确域名,不能是通配符 -
Access-Control-Max-Age:建议设为
1728000(20 天),减少重复预检请求
OPTIONS 预检请求必须显式返回 204
浏览器在发复杂请求前会先发一个 OPTIONS 请求。Nginx 默认不处理它,容易返回 405 或空响应,导致跨域失败:
- 在对应
location块内加if ($request_method = 'OPTIONS') { ... return 204; } - 里面要重复设置所有 CORS 头(包括
Origin、Methods、Headers等) - 必须加
add_header 'Content-Length' 0;和add_header 'Content-Type' 'text/plain; charset=utf-8'; -
return 204;是关键,它终止后续流程,避免被proxy_pass或其他逻辑干扰
动态匹配白名单 Origin(推荐生产环境用)
硬编码单个域名不灵活,多前端或测试环境难维护。用 map 指令实现源动态校验:
- 在
http块顶部定义映射:
default "";
~^https?://(www\.)?your-domain\.com(:[0-9]+)?$ $http_origin;
~^https?://(localhost|127\.0\.0\.1):[0-9]+$ $http_origin;
}
- 然后在
location中用add_header 'Access-Control-Allow-Origin' $cors_origin; - 这样既支持正式域名,也兼容本地开发,还能自动拒绝非法来源
别把 add\_header 和 proxy\_set\_header 搞混
这是最常见误区:
-
add_header是加给浏览器看的响应头,CORS 全靠它生效 -
proxy_set_header是加给后端看的请求头,比如传X-Real-IP,对跨域完全无效 - 浏览器跨域检查只认最终响应里的
Access-Control-*字段,和后端是否收到某个头毫无关系











