灰度发布时必须用map指令动态白名单校验Origin,禁用*和硬编码,仅对staging-fe.example.com、beta.myapp.net、localhost:3000等灰度域名放行CORS头,配合always确保响应头注入,并拦截OPTIONS返回204。

灰度发布时,只允许测试前端域名跨域访问,核心是让 Nginx 动态识别请求来源,并仅对白名单中的域名放行 CORS 头——不能用 *,也不能硬编码固定域名,得灵活、安全、可维护。
明确灰度环境的域名白名单
先梳理清楚哪些前端域名属于灰度流量,比如:
https://staging-fe.example.comhttps://beta.myapp.net-
http://localhost:3000(开发联调用)
这些域名需精确匹配协议+主机名+端口(若非标准端口)。注意:http://localhost 和 https://localhost 是不同源,需分别列出。
用 map 指令动态映射合法 Origin
Nginx 原生不支持多值 add_header,但可通过 map 模块将 $http_origin 映射为可信值或空字符串。在 http 块中定义:
立即学习“前端免费学习笔记(深入)”;
map $http_origin $cors_origin {
default "";
"~^https?://staging-fe\.example\.com(:[0-9]+)?$" $http_origin;
"~^https?://beta\.myapp\.net(:[0-9]+)?$" $http_origin;
"~^http://localhost:3000$" $http_origin;
}说明:
- 正则以
~^开头表示大小写敏感匹配;https?兼容 http/https;\.转义点号;(:[0-9]+)?可选端口 - 匹配成功时,
$cors_origin等于原始Origin值,用于响应头;不匹配则为空,Nginx 不添加该 header - 避免使用
if判断$http_origin,因if在 location 中有坑,map 更安全高效
在 location 中启用带凭证的 CORS 响应
灰度前端常需携带 Cookie 或 Token,因此必须开启 Access-Control-Allow-Credentials,同时 Access-Control-Allow-Origin 必须是具体域名(不可为 *):
location /api/ {
# 动态设置 Origin(仅对白名单生效)
add_header 'Access-Control-Allow-Origin' $cors_origin always;
add_header 'Access-Control-Allow-Credentials' 'true' always;
<pre class='brush:php;toolbar:false;'># 允许的方法与头部
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' 'Content-Length' always;
# 预检请求直接返回 204,不转发给后端
if ($request_method = 'OPTIONS') {
add_header 'Access-Control-Max-Age' 86400;
add_header 'Content-Type' 'text/plain; charset=utf-8';
add_header 'Content-Length' 0;
return 204;
}
proxy_pass http://backend;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;}
关键点:
-
always参数确保即使后端返回 3xx/4xx/5xx,CORS 头仍会被添加 - 预检请求(OPTIONS)由 Nginx 拦截并快速响应,不透传到后端,降低负载
-
Access-Control-Allow-Credentials: true与$cors_origin配合,既支持登录态共享,又规避了*+ credentials 的规范冲突
验证与上线前检查
部署后务必验证三类请求:
- 来自
https://staging-fe.example.com的实际请求 → 应返回Access-Control-Allow-Origin: https://staging-fe.example.com且含Access-Control-Allow-Credentials: true - 来自
https://prod-fe.example.com的请求 → 响应中不应出现任何 CORS 头(浏览器视为拒绝跨域) - OPTIONS 预检请求 → 返回 204 状态码,且含所有 CORS 头,无 body
可用 curl 快速测试:
curl -H "Origin: https://staging-fe.example.com" \
-H "Access-Control-Request-Method: GET" \
-X OPTIONS -I http://your-nginx/api/users观察响应头是否符合预期。灰度期间建议配合日志记录 $http_origin 和 $cors_origin,便于排查误配。


















