Nginx中配置CSP需与HTTPS协同,通过分项约束script-src、style-src等资源加载源,禁用unsafe-inline/eval,显式声明object-src、base-uri等非资源入口,并启用report-to报告机制,统一由Nginx注入且加always参数确保全覆盖。

在 Nginx 中用 add_header Content-Security-Policy 配合 HTTPS,不是简单加一行头就能防住劫持——关键在于把 CSP 当作“资源访问的交通管制系统”,而 HTTPS 是这条道路的加密护栏。两者协同,才能堵住从协议层到加载层的全链路风险。
HTTPS 是 CSP 生效的前提基础
没有 HTTPS,CSP 的很多指令(比如 upgrade-insecure-requests、strict-dynamic、报告机制)会失效或被绕过。浏览器只在安全上下文中严格执行 CSP:
- 确保 Nginx 的
server { listen 443 ssl; }块已正确配置证书,并启用http2 - 所有前端资源(JS/CSS/图片/字体)必须通过
https://协议加载;HTTP 资源会被浏览器直接拦截,且不触发 CSP 报告 - 避免混合内容:即使页面是 HTTPS,若内联 script 或 iframe 指向 HTTP 地址,CSP 无法挽救——它只管“是否允许加载”,不管“协议是否匹配”
用 add_header 精准声明每类资源的可信边界
CSP 不是靠一个 default-src 'self' 就万事大吉。静态资源劫持常发生在字体、样式、连接请求等“非脚本但可载荷”的环节,必须分项约束:
-
script-src:禁用
'unsafe-inline'和'unsafe-eval';如需内联脚本,用nonce-xxx(前后端协同生成并注入)或sha256-xxx哈希校验 -
style-src:同样禁用
'unsafe-inline';若使用 Ant Design、Tailwind JIT 等运行时生成样式,需显式添加对应 CDN 域名(如https://cdn.jsdelivr.net) -
font-src:限定为
'self'或已知可信源(如fonts.gstatic.com),防止恶意字体文件携带隐蔽 payload -
img-src:允许
'self'和data:(小图标),禁止通配符*;特别注意 base64 图片可能被用于 exfiltration -
connect-src:限制 AJAX/fetch/WebSocket 连接目标,如仅允许
'self'和 API 域名,避免被用于探测内网或打点回传
堵住非资源类劫持入口与兜底漏洞
很多 CSP 失效,是因为忽略了非加载型攻击面和继承陷阱:
- 显式设置
object-src 'none'(禁用 Flash/Object)、base-uri 'self'(防 base 标签劫持跳转)、form-action 'self'(防表单提交被重定向到恶意地址) - 不要依赖
default-src自动继承:font-src、style-src、frame-src等指令不会自动继承default-src,必须单独声明,否则浏览器按宽松策略处理 - 避免使用
https:这种宽泛源——它允许任意 HTTPS 域名,等于开放劫持通道;宁可多写几个明确域名,也不要图省事用通配
用 report-to/report-uri 主动感知异常行为
再严格的策略也难覆盖所有动态场景。上线前必须启用报告机制,把浏览器变成你的“一线哨兵”:
- 在 server 块中添加:
add_header Content-Security-Policy "…; report-to csp-endpoint;" always;(新版)或report-uri /csp-report;(旧版) - 后端部署简易接收端(如 Express 的 POST /csp-report),记录
violated-directive、blocked-uri、document-uri - 重点关注
blocked-uri指向未知域名、data:协议、或包含可疑参数的请求——这往往是劫持试探或供应链污染的信号 - 建议先用
Content-Security-Policy-Report-Only模式运行 3–7 天,确认无误后再切为强制执行模式
不复杂但容易忽略:CSP 必须由 Nginx 统一注入,后端应用要移除所有自行输出的 CSP 头;同时确保 always 参数启用,否则 304、404、静态文件响应里头不会带上 CSP。


















