Nginx中add_header配置CORS需注意:仅对2xx/3xx响应生效,必须显式处理OPTIONS预检并返回204,且需配全Access-Control-Allow-Origin、Methods、Headers等头;建议用map动态匹配白名单Origin并加always参数确保生效。

在 Nginx 中用 add_header 配置 CORS 跨域策略,关键在于理解响应头的生效时机和覆盖规则——它只对 2xx 和 3xx 响应生效,且不会继承到子请求(如内部重定向),更不能替代 Access-Control-Allow-Origin 的动态匹配逻辑。
基础 CORS 头必须配全
仅设置 Access-Control-Allow-Origin 不足以让浏览器放行跨域请求。常见漏项会导致预检失败或响应被拦截:
-
Access-Control-Allow-Origin:指定允许的源(如https://example.com)或通配符*(注意:带凭证时不可用*) -
Access-Control-Allow-Methods:列出允许的 HTTP 方法,如GET, POST, PUT, DELETE, OPTIONS -
Access-Control-Allow-Headers:声明客户端可发送的自定义请求头,如Content-Type, Authorization, X-Requested-With -
Access-Control-Allow-Credentials:设为true才能携带 Cookie 或认证信息(此时Access-Control-Allow-Origin不能为*) -
Access-Control-Max-Age:缓存预检结果的秒数,减少重复 OPTIONS 请求
OPTIONS 预检请求要单独处理
add_header 对 4xx/5xx 响应无效,而浏览器发起的预检(OPTIONS)若未匹配到 location 块,可能返回 404 或 405,导致跨域失败。必须显式捕获并返回 204:
location /api/ {
# 正常接口代理
proxy_pass https://www.php.cn/link/65b5b8d1f89bf53a5713bc3afdd83e9e;
<pre class="brush:php;toolbar:false;"># 添加 CORS 响应头(仅对 2xx/3xx 生效)
add_header 'Access-Control-Allow-Origin' 'https://your-app.com';
add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS, PUT, DELETE';
add_header 'Access-Control-Allow-Headers' 'Content-Type, Authorization, X-Requested-With';
add_header 'Access-Control-Allow-Credentials' 'true';
add_header 'Access-Control-Max-Age' 1728000;
# 必须显式处理 OPTIONS 请求
if ($request_method = 'OPTIONS') {
add_header 'Access-Control-Allow-Origin' 'https://your-app.com';
add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS, PUT, DELETE';
add_header 'Access-Control-Allow-Headers' 'Content-Type, Authorization, X-Requested-With';
add_header 'Access-Control-Allow-Credentials' 'true';
add_header 'Access-Control-Max-Age' 1728000;
add_header 'Content-Length' 0;
add_header 'Content-Type' 'text/plain; charset=utf-8';
return 204;
}
}
避免 add\_header 被覆盖或丢失
add_header 在同级作用域中后定义的会覆盖先定义的;且子 location 中未重新声明时,不会自动继承父级的 header。常见陷阱:
- 不要在
http块全局加 CORS 头——静态资源、健康检查等非 API 接口不应暴露这些头 - 在
server或location块中配置,并确保所有需要跨域的路径都覆盖到 - 使用
always参数(Nginx 1.7.5+)可让 header 在所有状态码下生效:add_header Access-Control-Allow-Origin "https://your-app.com" always; - 调试时用
curl -I -H "Origin: https://your-app.com" https://yoursite.com/api/test检查响应头是否出现
生产环境建议:按需动态控制 Origin
硬编码 Access-Control-Allow-Origin 不够灵活。可通过 map 模块实现白名单匹配:
map $http_origin $cors_origin {
default "";
"~^https?://(localhost|your-app\.com|staging\.app\.com)$" $http_origin;
}
<p>server {
location /api/ {
proxy_pass <a href="https://www.php.cn/link/65b5b8d1f89bf53a5713bc3afdd83e9e">https://www.php.cn/link/65b5b8d1f89bf53a5713bc3afdd83e9e</a>;</p><pre class="brush:php;toolbar:false;"> add_header 'Access-Control-Allow-Origin' $cors_origin always;
add_header 'Access-Control-Allow-Credentials' 'true' always;
add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS, PUT, DELETE' always;
add_header 'Access-Control-Allow-Headers' 'Content-Type, Authorization, X-Requested-With' always;
if ($request_method = 'OPTIONS') {
add_header 'Access-Control-Allow-Origin' $cors_origin always;
add_header 'Access-Control-Allow-Credentials' 'true' always;
add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS, PUT, DELETE' always;
add_header 'Access-Control-Allow-Headers' 'Content-Type, Authorization, X-Requested-With' always;
add_header 'Content-Length' 0 always;
add_header 'Content-Type' 'text/plain; charset=utf-8' always;
return 204;
}
}
}
这样既安全又可控,避免了通配符带来的风险,也支持多域名部署。










