script-src 'self' 不足以防御 XSS,因仍允许内联脚本、事件和 eval;禁用内联需省略 'unsafe-inline' 并配合 nonce 或 hash;第三方脚本须精确匹配协议、域名、端口;开发应先用 Report-Only 模式收集日志;其他指令如 base-uri、form-action 等也需显式限制。

script-src 'self' 是最基础但不够安全的写法
只写 script-src 'self' 看似限制了脚本来源,实际仍允许所有内联脚本(<script>alert(1)</script>)、内联事件(onclick="doSomething()")和 eval() 类动态执行——这些正是 XSS 最常利用的入口。
它只阻止了跨域外部脚本,对页面自身注入毫无防御力。生产环境绝不能仅靠这个就认为“已启用 CSP”。
禁用内联脚本必须显式省略 'unsafe-inline',再选 nonce 或 hash
真正禁用内联脚本,不是加 'unsafe-inline' 的反向操作,而是:不写它,并配合合法化机制。
-
nonce适合动态生成的 HTML:服务端每次响应生成新随机值,如script-src 'self' 'nonce-r4nd0m123',对应 HTML 中<script nonce="r4nd0m123">...</script>;硬编码或复用 nonce 值等于失效 -
hash适合静态内联脚本:对脚本内容算 SHA256,如script-src 'self' 'sha256-BzLdO9X...';动态拼接的 JS 无法预计算 hash,别误用于模板渲染场景 - 两者可共存,但浏览器只匹配其一;没匹配上的脚本仍被拦截
引入第三方脚本时,域名必须精确匹配协议和端口
比如 Stripe 要求加载 https://js.stripe.com/v3/,配置就得写 script-src 'self' https://js.stripe.com,不能漏掉 https://,也不能写成 js.stripe.com(缺少协议会被拒绝)。
常见错误:
- 写
script-src 'self' cdn.jsdelivr.net→ 缺少协议,实际需https://cdn.jsdelivr.net - 写
script-src 'self' https://example.com:8080→ 若服务实际走 HTTPS 默认端口 443,8080 会失效 - 混用通配符:如
https://*.example.com在部分浏览器中不支持子域通配,应明确列出所需子域
开发阶段务必先用 Content-Security-Policy-Report-Only
直接上线严格策略容易导致功能白屏或中断,尤其当页面含富文本、管理后台、或依赖未声明的 CDN 时。
推荐流程:
- 先发
Content-Security-Policy-Report-Only响应头,搭配report-uri或report-to收集违规日志 - 观察 3–7 天,确认所有合法脚本都被覆盖,无误报拦截
- 再切换为
Content-Security-Policy并移除report-uri - 注意:
标签无法设置report-uri,且优先级低于响应头,生产环境必须走 HTTP 头
CSP 不是设完就完的事——base-uri、form-action、frame-ancestors 这些指令默认宽松,不显式声明就等于留后门。一个漏掉 form-action 'self' 的登录页,可能被诱导提交到钓鱼域名。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











