nginx server块配置cors的核心是精准设置响应头并正确处理options预检:必须用map定义可信origin白名单,禁用*配合credentials,通过if拦截options返回204,并加always确保header生效,同时proxy_hide_header避免后端头冲突。

在 Nginx 的 server 块中配置 CORS,核心是通过响应头控制浏览器是否放行跨域请求,并正确处理预检(OPTIONS)请求。关键不在于“加多少头”,而在于头的值是否匹配、是否覆盖、是否与凭证(credentials)逻辑一致。
基础安全配置:限制指定前端域名
生产环境严禁使用 * 作为 Access-Control-Allow-Origin 值,尤其当启用了 Access-Control-Allow-Credentials true 时——此时 Origin 必须是明确域名,不能为通配符。
- 先用
map指令定义白名单,支持正则匹配带端口或子域的来源:
map $http_origin $cors_origin {
default "";
"~^https?://(www\.)?myapp\.com(:[0-9]+)?$" $http_origin;
"~^https?://staging\.myapp\.com$" $http_origin;
}- 在
server块内直接引用该变量设置响应头:
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, PUT, DELETE, OPTIONS' always; add_header 'Access-Control-Allow-Headers' 'Content-Type, Authorization, X-Requested-With' always; add_header 'Access-Control-Expose-Headers' 'X-Total-Count, X-Request-ID' always;
必须单独处理 OPTIONS 预检请求
浏览器在发送复杂请求(如带自定义 header 或非简单 method)前,会先发一个 OPTIONS 请求。Nginx 若未显式返回 204,可能因无响应体导致 502 或超时。
- 在
server块中添加条件判断,拦截并快速响应:
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, PUT, DELETE, OPTIONS' always;
add_header 'Access-Control-Allow-Headers' 'Content-Type, Authorization, X-Requested-With' always;
add_header 'Access-Control-Max-Age' 1728000 always;
add_header 'Content-Length' 0 always;
add_header 'Content-Type' 'text/plain; charset=utf-8' always;
return 204;
}- 注意:
add_header ... always是必需的,否则在return 204分支中 header 不会生效; -
if在server级别可用,但不要嵌套在location内重复写——统一在server块顶部处理更清晰。
避免常见陷阱
CORS 失败常不是因为没加头,而是头之间冲突或逻辑矛盾。
- 如果后端本身也输出
Access-Control-Allow-Origin,Nginx 的add_header会与其叠加,导致响应头重复,浏览器拒绝——用proxy_hide_header屏蔽后端头:
proxy_hide_header 'Access-Control-Allow-Origin'; proxy_hide_header 'Access-Control-Allow-Credentials';
- 若需支持多个完全无关的域名(如客户定制化前端),仍用
map扩展规则,不要硬编码多个if; -
Access-Control-Allow-Credentials true和Origin: *绝对不可共存,Nginx 不会报错,但浏览器一定拦截。
验证配置是否生效
重启 Nginx 后,用 curl 模拟跨域请求检查响应头:
curl -H "Origin: https://myapp.com" -I https://api.example.com/health # 应看到含 Access-Control-Allow-Origin: https://myapp.com 的响应
- 再测试预检:
curl -X OPTIONS -H "Origin: https://myapp.com" -H "Access-Control-Request-Method: POST" -I https://api.example.com/api/v1/users
- 状态码应为 204,且包含所有预期的 CORS 头。











