最稳妥的方式是在 nginx 的 server 块设基础 csp 策略,再于 location 块按路径细化(如 /static/、/api/、/uploads/),所有 add_header 必须加 always 参数确保错误页也生效;上线前须先用 content-security-policy-report-only 模式收集 3–7 天违规日志,再逐步收紧策略,并同步启用 strict-transport-security、x-frame-options 等关键安全头。

在 Nginx 中配置 Content-Security-Policy(CSP),核心是用 add_header 指令注入响应头,但不能简单写一行就完事——策略必须分层、可调、带验证,否则容易导致页面白屏或功能异常。
分层配置:从 server 块起步,不直接写在 http 块
全局 ≠ 一刀切。http 块适合配 HSTS、X-Content-Type-Options 等通用安全头;CSP 应放在 server 块作为“准全局”基础策略,再按需在 location 块细化:
- 不同站点(如后台系统和官网)安全要求不同,统一 CSP 难以兼顾
- API 接口、上传路径、静态资源目录常需单独放行,比如
connect-src 'self' api.example.com - 错误页(4xx/5xx)默认不带 header,必须加
always参数才能覆盖
基础策略模板:兼顾兼容与防护
以下是一个适用于大多数 HTTPS 站点的起点配置,已避开常见坑点(如漏掉 data: 图片、禁用内联样式引发渲染异常):
add_header Content-Security-Policy "default-src 'self'; script-src 'self' 'unsafe-inline' 'unsafe-eval' https:; style-src 'self' 'unsafe-inline' https:; img-src 'self' data: https:; font-src 'self' https: data:; connect-src 'self' https:; frame-src 'self'; frame-ancestors 'self'; object-src 'none'; base-uri 'self'; form-action 'self'; upgrade-insecure-requests; block-all-mixed-content;" always;
-
'unsafe-inline'保留用于兼容传统内联事件(如onclick)或未改造的 CMS;若已迁移到 nonce/hash,则可移除并启用strict-dynamic -
data:必须显式加入img-src和font-src,否则 Base64 图片或字体将加载失败 -
upgrade-insecure-requests和block-all-mixed-content依赖 HTTPS,确保 server 块已启用listen 443 ssl
上线前必做:先用 Report-Only 模式收集日志
直接启用完整 CSP 风险高,推荐分两步走:
- 第一步:把
Content-Security-Policy换成Content-Security-Policy-Report-Only,搭配report-to或report-uri收集违规行为 - 第二步:分析日志,识别被拦截的合法资源(如 CDN 字体、统计 JS、第三方插件),再逐步收紧策略
- 浏览器只在安全上下文(HTTPS)中严格执行 CSP,HTTP 页面下部分指令会失效或被忽略
配合其他安全头形成合力
CSP 不是孤岛,需与其它响应头协同生效:
-
Strict-Transport-Security强制全站 HTTPS,是 CSP 升级指令(如upgrade-insecure-requests)的前提 -
X-Frame-Options: DENY或frame-ancestors 'none'防点击劫持,比仅靠 CSP 更可靠 -
X-Content-Type-Options: nosniff防止 MIME 类型混淆攻击,避免浏览器误执行非脚本文件











