Nginx中CSP应分层配置:http块设通用安全头,server块设基础策略,location块按需细化;必须加always参数,推荐先用Report-Only模式收集日志再渐进上线。

Content-Security-Policy(CSP)在 Nginx 层做全局配置,核心是用 add_header 指令统一注入响应头,但“全局”不等于“一刀切”——真正安全又可用的方案必须分层设计、按需细化,避免因策略过严导致功能异常或样式丢失。
全局配置的位置与适用范围
Nginx 中所谓“全局”,通常指 http 块级配置,对所有 server 和 location 生效。但实际中不推荐在 http 块直接写完整 CSP,原因有三:
- 不同虚拟主机(如管理后台 vs 公共官网)安全等级差异大,统一策略难以兼顾
- API 接口、上传目录、静态资源路径等需要特殊放行或严格限制,无法用一个策略覆盖
- 一旦配置错误,整个站点 JS/CSS 加载失败,影响面广且排查困难
更合理的做法是:在 http 块定义通用安全头(如 HSTS、X-Content-Type-Options),而 CSP 放到 server 块作为“准全局”基础策略,再按路径细化。
基础 server 级 CSP 模板(兼顾安全与兼容)
以下是一个适用于大多数 Web 应用的起点配置,已避开常见踩坑点(如误禁内联样式、遗漏 data: 图片、未处理字体加载):
server {
listen 443 ssl;
server_name example.com;
<pre class="brush:php;toolbar:false;"># 基础 CSP(主站默认策略)
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;}
注意:always 参数必须添加,否则 Nginx 默认不向 3xx/4xx 响应头中注入该字段,会导致错误页缺失防护。
关键指令的取舍逻辑与典型调整场景
CSP 不是固定字符串,每个指令都需结合业务判断。以下是高频调整点:
-
script-src:保留
'unsafe-inline'是为兼容传统内联事件(如onclick)和部分 CMS;若已迁移到外部脚本 + nonce 或 hash,则可移除并启用'strict-dynamic' -
frame-ancestors:设为
'self'允许同源嵌入,适合 SSO 登录页或微前端;若为独立后台,建议改'none'彻底防点击劫持 -
connect-src:必须明确列出 API 域名(如
api.example.com),不能只写https:,否则浏览器可能拒绝 fetch 请求 -
img-src:务必保留
data:,否则 Base64 图片(图标、小图)将无法显示
渐进式上线与监控机制
直接启用拦截模式风险高,应分两步走:
- 先用
Content-Security-Policy-Report-Only替换原指令,配合report-uri或report-to收集违规日志,观察真实用户行为 7–14 天 - 分析报告后,针对性放宽策略(如增加缺失 CDN 域名),再切换为正式 CSP 头
- 线上保留
report-uri /csp-report并配置对应后端接口,持续捕获绕过尝试或新型 XSS 尝试
例如启用报告模式的写法:
add_header Content-Security-Policy-Report-Only "default-src 'self'; report-uri /csp-report;" always;











