CSP 内容安全策略是什么?nonce 和 hash 如何限制脚本执行?
下面是一段教学模拟,不是真实面试记录。
🧑💻 面试官:页面怎样限制被注入的脚本执行?
🙋♂️ 我:加 CSP,只允许自己域名的脚本。
🧑💻 面试官:自己的域名下也有用户上传内容,白名单就绝对安全吗?
🙋♂️ 我:还可以用 nonce 或 hash。
🧑💻 面试官:nonce 固定写在配置里可以吗?hash 又是在校验哪一段内容?用了 CSP 就不用处理 XSS 了吗?
CSP 给浏览器提供「哪些代码允许执行」的规则。nonce 是本次响应的许可标记,hash 则绑定具体内容,都不是替代输入与输出安全处理的魔法。
面试速答(60 秒版)
CSP 是浏览器执行的内容安全策略,可以通过 script-src 等指令限制脚本来源与执行条件,降低注入内容变成可执行脚本的风险。
nonce 通常由服务端为每次响应生成不可预测的新值,同时放进策略与被允许的脚本标签。不能长期复用一个固定 nonce。
hash 则根据指定脚本内容计算,内容一致才获得许可,空格和换行变化也可能影响匹配,适合稳定的脚本内容。
上线前可以用 Report-Only 观察违规,再逐步执行策略。但 CSP 只是纵深防御,输出编码、危险 DOM 操作、第三方依赖和业务权限仍要处理。

知识点详解:脚本标签出现在页面里,为什么不一定能运行?
浏览器按策略检查可执行内容
假设页面意外插入了攻击者提供的脚本标签。如果没有适当限制,浏览器可能将它当成普通脚本执行。
CSP 让响应声明许可规则,例如哪些来源或哪些脚本标记可以执行。浏览器收到页面后按规则检查,并报告或阻止违规。
不过来源白名单需要仔细设计:可信域名里存在可被攻击者控制的内容,或者过于宽泛的许可,都会削弱效果。CSP 官方指南
nonce 应属于一次响应,而不是整个项目
教学策略可以写成:
Content-Security-Policy: script-src 'nonce-本次随机值'
被允许的脚本标签也需要带相同 nonce。实际值应由安全随机方式产生,不能真的使用上面的说明文字。
攻击者仅插入一个没有匹配标记的脚本,不应因此获得执行许可。若 nonce 长期固定且可预测,就削弱了这种区分。
服务端模板还要确保只给可信脚本添加标记,不能不加判断地给所有注入片段补 nonce。HTML 缓存、策略头和标签中的值也要保持一致。
nonce 不是用户登录凭证;它授权的是本次页面里的脚本执行,不是任意业务操作。
hash 绑定内容,改一行也要重新核对
对于稳定的内联脚本,可以按其精确内容生成哈希,再将对应表达式加入策略。
浏览器匹配的是脚本内容,不只是文件名,也不是“语义相同就算一致”。压缩、换行和空格变化,都可能需要重新计算。
如果脚本频繁包含动态数据,每次内容都变,维护 hash 会更复杂。此时可以调整内容组织或考虑 nonce,不应该为了免维护就加入宽松许可。
外部脚本 hash 还涉及额外规则与完整性属性,不能将内联脚本的简化例子直接推广。script-src 文档

Report-Only 用来观察,不会真的阻止
Content-Security-Policy-Report-Only 可以收集违反策略的情况,但它本身不进行同样的阻止。
因此,看到报告接口没有错误,不代表页面已经处在强制防护下。应确认真正执行的响应头,并测试正常脚本与违规脚本。
上线还要盘点第三方脚本、旧内联事件等兼容问题。可以逐步收紧,但不能用大范围 unsafe-inline 让报错消失之后,就宣称实现了严格脚本限制。
CSP 也不替我们修复所有 XSS:正确输出编码、安全 DOM API 和内容来源控制仍然必要。
面试官继续追问
nonce 在 HTML 中能看到,所以完全没有用吗?
不是。它的关键是每次响应不可预测、攻击者不能提前拿固定值拼进注入载荷。它不应被当成永久秘密,也不能因此长期复用。
hash 校验成功,就说明脚本安全了吗?
只说明内容匹配许可。被许可的内容本身如果有漏洞,CSP 不会替我们审计它。
应该如何验证策略有效?
检查浏览器收到的实际头,分别测试合法脚本、无许可内联脚本与第三方依赖,再分析违规报告。仅检查服务端配置文件不够。
面试速记卡
- CSP:由浏览器执行的内容许可规则,属于纵深防御。
- nonce:每次响应新生成、不可预测,策略与可信标签一致。
- hash:绑定精确脚本内容,内容变化需要重新核对。
- Report-Only:观察违规,不代表已经阻止执行。
- 防护边界:CSP 不替代输出编码、安全 DOM 与依赖审查。
公司面试真题
这道题暂未收录可核验的公司真题来源。你可以先阅读本文解析,或浏览已收录的公司面试真题。
浏览公司面试真题 →