CSP 头部生成器
通过指令、hash 与 nonce 构建 Content-Security-Policy 头部。含严格模式模板、Report-Only 调试模式以及 Express、Nginx 片段。在浏览器中运行。
- 在浏览器中处理
- 数据不离开你的设备
- 免费 · 无需注册
用微信扫描以下二维码即可分享
示例、说明与常见问题 带实际输出的示例、与同类工具的差别,以及常见问题。
Strict CSP 起步配置
Strict 预设采用 web.dev 介绍的基于 nonce 的 strict CSP。HTTP header 页签输出:
Content-Security-Policy: default-src 'self'; script-src 'nonce-{RANDOM}' 'strict-dynamic'; style-src 'self'; img-src 'self' data:; font-src 'self'; connect-src 'self'; object-src 'none'; base-uri 'self'; form-action 'self'; frame-ancestors 'none'; upgrade-insecure-requests
'nonce-{RANDOM}' 是占位符,不是可用的值。服务器必须在每次响应时把它换成至少 128 位的新随机值,并把同一个值写进它渲染的每个 <script> 的 nonce=”…”。只要策略里还有占位符,工具就会显示警告。不要把一个固定的 nonce 写进静态配置:任何人看到一次就能在注入的脚本里重复使用。
早期版本的这个预设写的是 ‘self’,现在换成了占位符。原因是有 ‘strict-dynamic’ 时,CSP Level 3 会拦截 HTML 解析器插入的所有脚本,除非带有匹配的 nonce 或 hash,并且不再检查 ‘self’ 和主机源(CSP3 §8.2)。所以单独的 script-src ‘self’ ‘strict-dynamic’ 在当前的 Chrome、Firefox、Safari 里一个脚本都不会执行,工具现在会对这种组合给出警告。如果站点是无法设置 nonce 的静态构建,删掉占位符,用 hash 计算器为每段内联脚本加 hash,或者从「适中」预设开始。
Express (helmet) 页签替你完成按响应生成这一步:它加一个中间件,把 crypto.randomBytes(16).toString(‘base64’) 存进 res.locals.cspNonce,并给 script-src 传一个函数,这是 helmet README 里的写法。模板仍要把这个值输出到每个 script 标签上。Nginx 页签保留占位符并加一行注释,因为 Nginx 无法把同一个 nonce 写进应用渲染出的 HTML。
容易踩的坑
’none’只能单独使用。 与其他源同列时‘none’不起作用,其他源照常放行。- 有些指令只在 HTTP 头部生效。 CSP3 §3.3 规定
<meta>里的frame-ancestors、report-uri、sandbox无效,也没有 Report-Only 模式。工具会在<meta>页签去掉它们并提示。 ‘strict-dynamic’必须搭配 nonce 或 hash。 没有时页面上的脚本会全部被拦截,工具会提示。- hash / nonce 会让
‘unsafe-inline’失效。 现代浏览器会优先采用更安全的策略。 - 务必声明
default-src。 缺失的 fetch 指令会回退到default-src;没有它,未来新增的指令也得不到任何兜底。 - 自定义主机不能包含分号。 分号会终止策略,把后续指令一并破坏。
Hash 还是 Nonce?
对于静态内联内容(埋点片段、关键 CSS、服务端渲染的辅助脚本),用 hash。它和静态 HTML、边缘缓存兼容,不需要每次请求都生成新值。
对于动态渲染内容,用 nonce。服务端在头部里写 ‘nonce-XYZ’,并在所有 <script nonce=“XYZ”> 上盖同一个值。把 nonce 与 ‘strict-dynamic’ 组合使用,可以让被信任脚本的子脚本继承信任,而你不必维护庞大的主机白名单。
部署速查
- Nginx:把 Nginx 页签的内容粘贴到
server块并 reload。always标志让错误响应也带上头部。 - Apache:在
.htaccess或httpd.conf里写Header always set Content-Security-Policy ”…”。 - Express / Node:粘贴 helmet 片段。务必关闭
useDefaults,避免你的策略被 helmet 默认值悄悄合并。 - Cloudflare Pages / Vercel / Netlify:把 HTTP header 写进各自的 headers 配置(
_headers、vercel.json、netlify.toml)。
FAQ
什么是 Content Security Policy?
CSP 是一类 HTTP 响应头部,用于声明浏览器允许加载的脚本、样式、图片、字体、iframe 等内容来源。结合输出编码,它是抵御 XSS、点击劫持与数据注入的最强浏览器侧防线。
上线时应该先用 Enforce 还是 Report-Only?
强烈建议先用 `Content-Security-Policy-Report-Only` 配合 `report-uri`(或 `report-to`)端点。先观察真实流量 1-2 周,把误伤改完,再切到强制生效的 `Content-Security-Policy`。
我必须用 'unsafe-inline' 才能写 inline script / style 吗?
不必。现代 CSP 支持按内容计算的 hash(`'sha256-...'` 等)以及按请求生成的 nonce(`'nonce-...'`),优先使用这两种方式。直接用页面里的 hash 计算器即可。
'strict-dynamic' 起什么作用?
它允许已经被 nonce 或 hash 信任的脚本在运行时再加载其他脚本,而无需一一列出 CDN 主机。这是现代应用推荐的模式,会覆盖基于主机的白名单,从而堵住绕过路径。
生成的头部应该部署到哪里?
请从源站发出 `Content-Security-Policy`(Nginx `add_header`、Apache `Header set`、Cloudflare Transform Rules、Vercel `headers` 等都可以)。HTML `<meta http-equiv>` 仅作为静态托管的兜底;CSP Level 3 规定 `<meta>` 里的 `frame-ancestors`、`report-uri`、`sandbox` 无效,工具在该页签中会去掉它们。`report-to` 在 `<meta>` 中仍有效,但它的端点要由 `Reporting-Endpoints` 头部定义。