content-security-policy 必须通过 http 响应头配置才生效,html 的 标签无效;需服务器返回如 content-security-policy: default-src 'self'; script-src 'self' https://cdn.example.com,禁用 'unsafe-inline',改用 nonce 或 hash;file:// 协议下 csp 完全不工作;report-uri 已废弃,应使用 report-to 配合 report-to 响应头。

Content-Security-Policy 响应头怎么配才生效
直接写在 HTML 的 <meta> 里基本没用,浏览器只对响应头里的 Content-Security-Policy 严格执行。开发时容易误以为加个 meta 标签就万事大吉,结果 XSS 还在跑。
实操建议:
- 必须由服务器返回 HTTP 响应头:
Content-Security-Policy: default-src 'self'; script-src 'self' https://cdn.example.com - Nginx 配置示例:
add_header Content-Security-Policy "default-src 'self'; script-src 'self' 'unsafe-inline'";(注意引号嵌套和空格) - 本地开发用
http-server -p 8080 --cors --headers headers.json,headers.json里写好 CSP 字段 - Chrome DevTools → Network → 点开 HTML 请求 → Headers → Response Headers 里必须看到
content-security-policy才算真正启用
script-src 里为什么不能随便加 'unsafe-inline'
加了它,所有内联 <script>alert(1)</script> 和 onclick="doSomething()" 都会绕过 CSP,等于策略形同虚设。
常见错误现象:页面功能正常了,但审计工具报高危,或者上线后被插入恶意 inline 脚本。
立即学习“前端免费学习笔记(深入)”;
替代方案:
- 把内联脚本全抽成外部文件,用
<script src="/js/main.js"></script> - 需要保留内联?改用
nonce:服务端生成随机值(如abc123),响应头写script-src 'nonce-abc123',对应 script 标签加nonce="abc123" - 或用
hash:计算脚本内容 SHA256,写进策略,如script-src 'sha256-abc...xyz'(适合构建时确定的静态代码)
为什么本地 file:// 协议下 CSP 完全不工作
浏览器明确不支持对 file:// URL 应用 CSP。双击打开 HTML、VS Code Live Server 默认端口未启用 HTTPS、Electron 主窗口未设 webSecurity: true —— 这些场景下,无论怎么写 <meta> 或响应头都无效。
使用场景判断:
- 开发调试时用
python3 -m http.server 8000启一个本地 HTTP 服务,而不是双击打开 - Webpack/Vite 开发服务器默认支持,但需确认实际响应头里有 CSP(有些插件默认不加)
- Electron 中必须显式设置
webPreferences: { webSecurity: true },否则 CSP 被忽略 - 测试时用 curl 查响应头:
curl -I http://localhost:8000/index.html,看有没有content-security-policy
report-uri 和 report-to 在现代浏览器里怎么选
report-uri 是旧标准,Chrome 94+ 已废弃;现在必须用 report-to + Report-To 响应头配合,否则违规报告发不出去。
性能与兼容性影响:
-
report-to的值是个 endpoint 名字(如"csp-endpoint"),不是真实 URL;真实地址要靠单独的Report-To响应头定义 - 示例组合:
Report-To: {"group":"csp-endpoint","max_age":3600,"endpoints":[{"url":"https://logs.example.com/csp"}]}Content-Security-Policy: default-src 'self'; report-to csp-endpoint - Firefox 110+、Safari 17.4+ 支持
report-to;老版本仍需降级 fallback 到report-uri(但别指望它在新版有效) - 报告是异步发送的,不会阻塞页面,但 endpoint 必须支持 CORS 和 POST,且返回 2xx
script-src 条目、每处 nonce 生成逻辑、每次本地调试路径,都会让策略实际效果打折扣。最常被跳过的其实是验证环节:没真用 curl 或 DevTools 确认响应头存在,也没模拟一次违规脚本看报告是否发出。











