CSP生产环境必须通过HTTP响应头配置,禁用meta标签;核心是default-src 'none'打底,显式声明script-src、connect-src等指令,并用nonce或hash替代unsafe-inline。

别用 <meta http-equiv="Content-Security-Policy"> 做生产防御——它拦不住内联脚本、不支持 nonce、会被响应头覆盖,上线即失效。
为什么 <meta> 标签在真实场景中基本无效
浏览器解析 HTML 是自上而下流式进行的:<script>alert(1)</script> 或 <button onclick="xss()"> 在解析到对应标签时立刻执行,而 <meta> 标签必须等解析到它所在位置才注册策略,此时恶意代码早已跑完。
- Safari 16.4 之前版本直接忽略含
nonce-或sha256-的script-src指令 - Chrome 124+ 已移除对
script-src 'unsafe-inline'在<meta>中的解析支持 - 只要服务端返回任意
Content-Security-Policy响应头(哪怕拼写错误),<meta>就被完全丢弃 -
file://协议下所有 CSP 全面关闭,本地测试毫无意义
Content-Security-Policy 响应头必须怎么写才起效
核心是:用 default-src 'none' 打底,再显式放开必需资源类型。漏配任何一类,对应资源就静默失败(比如没写 img-src,base64 图片就炸)。
-
default-src 'none'是起点,不是可选项;它让所有未声明的资源类型默认拒绝 -
script-src 'self'不够——它只限制外链脚本,放行所有内联脚本;必须去掉'unsafe-inline',并配nonce或哈希 -
connect-src 'self'必须显式写,否则fetch()、WebSocket会因策略缺失被拦截 -
base-uri 'self'、form-action 'self'、frame-ancestors 'none'、object-src 'none'这四条不设等于留后门
示例(Nginx 配置):
add_header Content-Security-Policy "default-src 'none'; script-src 'self' 'nonce-$request_id'; style-src 'self' 'unsafe-inline'; img-src 'self' data:; font-src 'self'; connect-src 'self'; base-uri 'self'; form-action 'self'; frame-ancestors 'none'; object-src 'none'";
使用 PptxGenJS 和 Python 解析,将结构化的 HTML/CSS 幻灯片内容转换为原生、可编辑的 PowerPoint(.pptx)演示文稿。
立即学习“前端免费学习笔记(深入)”;
nonce 怎么用才不踩坑
nonce 不是开关,是信任链的起点。首屏 JS 标签没带匹配 nonce,后续所有动态创建的 <script> 都会被 strict-dynamic 拒绝。
-
nonce值必须每次 HTTP 响应唯一,不能硬编码或复用;推荐用请求 ID 或加密随机数生成 - 响应头里写
script-src 'nonce-abc123' 'strict-dynamic',HTML 中对应<script nonce="abc123">才生效 - 禁止混用
'self'和'strict-dynamic':写成script-src 'self' 'strict-dynamic'会导致浏览器忽略后者,回退到源匹配 - Webpack/Vite 构建产物若含热更新脚本或
import()动态 chunk,需确认构建工具是否注入nonce,否则这些脚本会被拦截
上线前必须验证的三件事
CSP 容易因架构细节失效,尤其在已有复杂前端的项目中。灰度期观察比硬切更可靠。
- 用
Content-Security-Policy-Report-Only+report-to收集 3–7 天真实违规日志,确认所有合法脚本、API 请求、字体、图片都被覆盖 - 检查第三方 SDK(如 Sentry、支付宝 JS SDK)是否在
script-src白名单中;漏掉一个,监控或支付功能就挂 - 富文本渲染、
v-html、dangerouslySetInnerHTML插入的内容若含 JS 执行逻辑(如javascript:void(0)),会被script-src拦截,得改用事件委托或预编译模板
真正难的不是写那行 header,而是把每个动态加载入口、每段服务端注入的初始化代码、每个第三方脚本都纳入策略覆盖范围——漏掉一个,整个防护就出现裂缝。


















