关键在于让每一层代理都明确透传并补全cors响应头,而非依赖某一层“一次性加完”;cdn、slb、waf等中间层默认不透传access-control-*头,须手动开启透传;cors头应在最靠近后端的nginx生成并用always参数确保所有状态码下生效。

关键在于让每一层代理都明确透传并补全 CORS 相关响应头,而不是依赖某一层“一次性加完”。多层代理(比如 Nginx → CDN → SLB → 后端 Nginx)中,任何中间层未配置透传或主动过滤,都会导致 Access-Control-Allow-Origin 等头部丢失,前端静默失败。
每层代理必须显式启用响应头透传
CDN(如阿里云 CDN、腾讯云 CDN)、负载均衡器(如 CLB、SLB)、WAF 或防火墙插件默认不透传自定义响应头。必须手动开启:
- 在 CDN 控制台找到「HTTP 响应头设置」或「缓存策略」,勾选「透传响应头」或「保留自定义 Header」
- 在负载均衡器后台,确认「转发规则」中启用了「透传响应头」,禁用「自动移除未知响应头」选项
- 宝塔面板若启用了「网站监控」或「防火墙插件」,需进入插件设置,关闭「响应头过滤」或白名单添加
Access-Control-*类头部
避免在非末端代理上做 CORS 头决策
CORS 头应在最靠近后端的那层 Nginx(即业务网关层)生成,而非前置 CDN 或 LB 上硬编码。原因:
- CDN 无法识别
$http_origin,没法做动态白名单校验 - LB 通常不支持
map或if指令,强行配置易出错或被忽略 - 只有最后一层反向代理能可靠获取原始请求头(如
Origin),并结合后端实际响应状态决定是否加头
用 always 参数确保头不被覆盖或丢弃
Nginx 的 add_header 默认只对 2xx 和 3xx 响应生效,而预检请求返回 204、错误返回 4xx/5xx 时头会被跳过。必须加 always:
add_header 'Access-Control-Allow-Origin' $cors_origin always;add_header 'Access-Control-Allow-Methods' 'GET, POST, OPTIONS' always;add_header 'Access-Control-Allow-Headers' 'Content-Type, Authorization' always;
否则,OPTIONS 请求返回 204 时头根本不会发出,浏览器判定预检失败。
验证真实响应链路是否完整
别只看浏览器开发者工具——它显示的是最终到达前端的响应,可能已被某层缓存或重写。直接用 curl 逐层探测:
-
curl -I https://your-api.com/path—— 看最终域名返回的头 -
curl -I --resolve your-api.com:443:10.0.1.100 https://your-api.com/path—— 绕过 DNS,直连网关层 Nginx IP,确认它是否输出了正确头 - 若两者不一致,说明中间某层(CDN/LB)吞掉了头,此时回对应控制台检查透传设置











