跨域响应头丢失本质是配置未覆盖转发链路各环节,须由最外层nginx统一管控cors头、禁用后端自动注入、逐层透传origin、用map动态白名单校验源,并拦截重写302跳转以保cors有效。

跨域响应头在 Nginx 负载均衡后丢失,本质不是“头被删了”,而是配置没覆盖到转发链路的每个环节——尤其当请求经过多级代理、或后端服务也输出 CORS 头时,容易冲突、覆盖或未透传。解决关键在于:统一由最外层 Nginx 控制 CORS 响应头,禁用下游干扰,并确保 Origin 等关键请求头完整抵达。
只在最外层 Nginx 统一加 CORS 头,关掉所有后端的自动 CORS
后端框架(如 Spring Boot 的 @CrossOrigin、Express 的 cors())若自行注入 Access-Control-Allow-Origin,和 Nginx 的 add_header 叠加会导致响应头重复,Nginx 报错或浏览器拒绝。必须做到:
- 关闭所有后端服务的 CORS 自动配置,让它们只专注业务逻辑
- 在最外层 Nginx 的
server或location块中集中设置 CORS 响应头 - 使用
add_header ... always,确保 302、401 等非 200 响应也能带 CORS 头
动态校验 Origin,避免通配符 * 与 credentials 冲突
如果前端需要携带 Cookie(credentials: 'include'),就不能用 Access-Control-Allow-Origin: *,否则浏览器直接报错。推荐用 map 白名单方式安全放行:
- 在
http块顶部定义可信源映射:
default "";
"https://your-fe.com" "$http_origin";
"https://staging-fe.com" "$http_origin";
}
- 在 location 中引用:
add_header 'Access-Control-Allow-Credentials' 'true' always;
确保 Origin 请求头逐层透传不中断
负载均衡常有多级 Nginx(如 CDN → 边缘 Nginx → 应用 Nginx),而默认情况下 $http_origin 不会自动向下传递。每层都必须显式透传:
- 在每一级的
location块中加:proxy_set_header Origin $http_origin; - 确认
proxy_pass_request_headers on;(虽默认开启,显式写出更可靠) - 若用了自定义头如
gray_origin,需先开underscores_in_headers on;,再加proxy_set_header gray_origin $http_gray_origin;
拦截并重写 302 Location,防止跳转后 CORS 失效
后端返回 302 时,浏览器会用新地址发起**全新跨域请求**,此时 Origin 丢失、CORS 头不继承。不能依赖后端补头,而应在 Nginx 层拦截处理:
- 启用错误拦截:
proxy_intercept_errors on; - 捕获 302 并跳转到同源路径:
error_page 301 302 = @handle_redirect; - 在
@handle_redirect中用return 302 $sent_http_location;发起跳转,并手动附加 CORS 头











