必须用 nginx 的 map 指令结合 pcre 正则动态匹配多级子域名,严格白名单放行;需在 http 块定义 map、location 中显式设置 cors 头(含 always 和 credentials 支持),并单独处理 options 预检请求返回 204。

支持复杂多级子域名(如 app.v2.beta.example.com、dashboard.api.internal.company.co.uk)的跨域请求,不能依赖静态域名列表或通配符 *(尤其当启用 credentials 时),必须用 Nginx 的 map 指令实现**正则动态匹配**,结合严格白名单逻辑来安全放行。
用 map 构建可扩展的多级子域名白名单
直接写死每个子域名不现实,应提取共性模式。例如允许所有 *.example.com 及其任意深度子域,同时排除测试或内部不可信域名:
- 在
http块顶层定义map,避免重复解析 - 用
~^开头的 PCRE 正则精确匹配 Origin 头 - 支持嵌套层级:比如
~^https?://([a-zA-Z0-9.-]+\.)?example\.com(:\d+)?$可匹配https://a.b.c.example.com和http://example.com:3000 - 显式拒绝已知风险域名(如
staging.example.com、dev.internal),用default ""确保未匹配项为空,不触发 CORS
location 中引用并强制生效
把 map 结果注入响应头,关键点在于:
-
add_header 'Access-Control-Allow-Origin' $cors_origin always;——always参数确保即使后端返回 4xx/5xx,CORS 头仍存在 - 若需携带 Cookie 或认证信息,必须同步设置:
add_header 'Access-Control-Allow-Credentials' 'true'; - Origin 值必须与请求头中完全一致(协议、主机、端口),Nginx 不会自动补全或标准化,所以正则要覆盖常见变体(
http/https、带端口/不带端口)
预检请求(OPTIONS)必须独立处理
浏览器对多级子域的预检更敏感,Nginx 不能只靠后端响应,必须主动拦截:
- 在对应
location内写if ($request_method = 'OPTIONS') { ... return 204; } -
if块内需**重复声明所有 CORS 头**(add_header不继承作用域),包括Allow-Origin、Allow-Methods、Allow-Headers - 返回
204 No Content,不带响应体,避免因Content-Length不一致导致失败
验证与调试技巧
配置生效后,重点验证三项:
- 用
curl -H "Origin: https://app.v2.beta.example.com" -I http://your-nginx/api/xxx检查响应头是否含正确Access-Control-Allow-Origin - 发起真实跨域请求(带
credentials: true),观察浏览器控制台是否报 “origin does not match” 错误 - 检查 Nginx error log,确认无
invalid regex或map variable undefined类警告











