nginx 中应使用 location 块精准配置 cors 响应头,按路径(如 /api/)启用跨域,添加 access-control-allow-origin 等头,并用 if 拦截 options 预检请求返回 204,支持动态来源匹配与 credentials。

在 Nginx 中,用 location 块精准控制跨域响应头,是最常用也最推荐的做法。它能按路径(比如 /api/)、方法或来源动态添加 CORS 头,避免全局放行带来的安全隐患。
只对特定路径启用跨域(如 /api/)
这是最典型的场景:前端调用后端 API 时跨域,而静态资源(HTML、JS、CSS)不涉及跨域问题。只需在对应 location 块中添加响应头:
-
add_header 'Access-Control-Allow-Origin' '*' always;—— 允许任意域名访问(开发环境可用;生产环境建议写具体域名) -
add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS, PUT, DELETE' always;—— 明确列出允许的 HTTP 方法 -
add_header 'Access-Control-Allow-Headers' 'Content-Type, Authorization, X-Requested-With' always;—— 包含前端实际发送的请求头,尤其是带 Token 或 JSON 的请求 -
add_header 'Access-Control-Allow-Credentials' 'true' always;—— 若需携带 Cookie 或认证信息,必须加此项,且此时Access-Control-Allow-Origin不能为*,得写成具体域名(如https://myapp.com)
必须处理 OPTIONS 预检请求
当请求含自定义头(如 Authorization)或非简单方法(如 PUT、DELETE),浏览器会先发一个 OPTIONS 请求探路。Nginx 必须拦截并快速响应,否则跨域失败:
- 用
if ($request_method = 'OPTIONS') { ... return 204; }拦截预检请求 - 在
if块内重复设置关键 CORS 头(特别是Allow-Origin和Allow-Methods),因为预检响应也需通过校验 -
return 204;表示成功响应且无正文,比200更规范 - 可选加
add_header 'Access-Control-Max-Age' 1728000;缓存预检结果 20 天,减少重复请求
按来源动态放行(更安全)
若前端有多个合法域名(如开发 http://localhost:3000、测试 https://test.myapp.com、线上 https://www.myapp.com),不建议硬编码单个域名,可用正则匹配动态设置:
if ($http_origin ~ ^(http://localhost:3000|https://(test|www)\.myapp\.com)$) {add_header 'Access-Control-Allow-Origin' $http_origin always;add_header 'Access-Control-Allow-Credentials' 'true' always;}- 这样既支持凭证,又避免了
*与true冲突的问题
注意 add_header 的作用域和 always 标志
add_header 默认不继承父级块,且仅对成功响应(2xx、3xx)生效。常见坑点:
- 没加
always时,4xx/5xx 错误响应不会带 CORS 头,导致浏览器连错误详情都看不到 - 应在
location块内直接添加,不要放在server或http级别做全局配置,除非所有路径都需跨域 - 如果同时用了
proxy_pass,确保 CORS 头加在location块里,而不是被后端覆盖











