Nginx 的 map 指令通过 $host 动态映射 CSP 策略,实现多区域(CN/US/EU)差异化安全策略;配合 always 参数、geo 模块兜底、/api/ 路径强化限制及 $request_id 支持 nonce,构建完整动态 CSP 方案。

Nginx 的 map 指令是实现多区域负载均衡站点 CSP 策略动态化的关键——它让安全策略能随请求来源(如子域名、地域标识、请求头)实时变化,而不是靠一堆重复的 location 块硬编码。
核心思路很直接:把 CSP 各字段(如 default-src、script-src)变成变量,用 map 根据 $host 或其他变量映射出对应值,再通过 add_header 注入。这样既保持配置简洁,又天然适配负载均衡后多个区域入口(如 cn.example.com、us.example.com、eu.example.com)各自不同的资源信任列表。
用 $host 区分子域名并映射 CSP 策略
这是最常用也最稳妥的方式。不同区域站点通常使用独立子域名,$host 可靠、稳定、无需额外模块支持。
-
map在http块顶部定义,匹配子域名正则(注意转义点号) - 每个区域对应一套
default-src和script-src规则,例如:- CN 站点:放行国内 CDN(
https://cdn-cn.example.com)、统计 JS(https://s95.cnzz.com),允许'unsafe-inline' - US 站点:放行 Google Fonts、GA4、Tag Manager
- EU 站点:更严格,禁用内联脚本,只允同源和指定欧盟合规服务(如
https://fonts.googleapis.com、https://consent.example.eu)
- CN 站点:放行国内 CDN(
示例配置:
http {
map $host $csp_default_src {
~\.cn\.example\.com "'self' https://cdn-cn.example.com https://s95.cnzz.com";
~\.us\.example\.com "'self' https://fonts.googleapis.com https://www.googletagmanager.com";
~\.eu\.example\.com "'self' https://fonts.googleapis.com https://consent.example.eu";
default "'self'";
}
map $host $csp_script_src {
~\.cn\.example\.com "'self' 'unsafe-inline' https://s95.cnzz.com";
~\.us\.example\.com "'self' 'unsafe-inline' https://www.googletagmanager.com";
~\.eu\.example\.com "'self' https://consent.example.eu";
default "'self'";
}
server {
listen 443 ssl;
server_name ~^(?<region>[a-z]{2})\.example\.com$;
add_header Content-Security-Policy "default-src $csp_default_src; script-src $csp_script_src; object-src 'none'; base-uri 'self';" always;
}
}⚠️ 注意:必须加
always参数,否则 301/404/静态资源响应不会携带 CSP 头,导致策略失效或前端报错不可见。
结合 geo 模块做 IP 地域兜底(可选增强)
当子域名未覆盖全部流量(比如用户直连 IP 或泛解析),可用 geo 指令按客户端 IP 划分大区,生成 $geo_region 变量,再用 map 二次映射为 CSP 值。
- 先在
http块中定义geo:geo $remote_addr $geo_region { default ""; include /etc/nginx/geoip.conf; # 需提前生成,含 CN/US/EU 网段 } - 再
map $geo_region补充策略,与$host映射逻辑解耦,便于灰度或降级。
API 接口路径单独强化限制
即使主站策略宽松,/api/ 路径应默认禁止脚本执行,防止接口被 XSS 利用:
location ^~ /api/ {
add_header Content-Security-Policy "default-src 'none'; script-src 'none'; connect-src 'self';" always;
}该配置优先级高于 server 块中的全局 CSP,且 always 保证错误响应也生效。
动态 nonce 支持内联脚本(高性能场景必需)
若前端大量使用 <script nonce="...">,需每次请求生成唯一 nonce。Nginx 自带 $request_id 是理想选择:
map $host $csp_nonce {
~\.cn\.example\.com "nonce-$request_id";
~\.us\.example\.com "nonce-$request_id";
~\.eu\.example\.com "nonce-$request_id";
default "nonce-$request_id";
}
# 然后在 CSP 中引用
add_header Content-Security-Policy "default-src $csp_default_src; script-src $csp_script_src $csp_nonce;" always;✅ 前端需同步将
$request_id注入 HTML 的<script nonce="...">,后端渲染或 Nginxsub_filter可配合实现。
不复杂但容易忽略

















