部署内容安全策略(CSP)而不破坏网站

Security2026-09-18TryQuickToolBox

你听说过内容安全策略(CSP)对于保护网站免受跨站脚本(XSS)和数据注入攻击至关重要。但当你尝试添加它时,网站却崩溃了:图片消失,脚本停止运行,样式不见了。感觉就像是在安全性和功能性之间做取舍。其实不必如此。

在本指南中,你将学习一种实用、分步的方法来部署CSP而不破坏网站。我们将涵盖核心指令、如何使用nonce和哈希,以及如何安全测试。到最后,你将拥有一个既能增强安全性又不牺牲用户体验的有效CSP。

什么是CSP,为什么它会破坏网站?

内容安全策略是一种浏览器安全标准,允许你限制页面上可以加载哪些资源(脚本、样式、图片、字体等)。它通过HTTP头传递,例如Content-Security-Policy: default-src 'self'。

CSP会破坏网站,因为它会阻止任何不符合策略的资源。如果你有内联脚本、来自CDN的外部脚本或内联样式,除非你明确允许,否则它们都会被阻止。默认行为是阻止所有未允许的内容,这就是为什么严格的策略会很快破坏网站。

关键是从宽松的策略开始,在监控违规的同时逐步收紧。

你需要了解的核心CSP指令

CSP使用指令来控制不同的资源类型。以下是最常见的指令:

你可以在一个头中设置多个指令,用分号分隔。例如:

Content-Security-Policy: default-src 'self'; script-src 'self' https://trusted.cdn.com; style-src 'self' 'unsafe-inline'; img-src 'self' data: https://images.example.com

每个指令接受一个以空格分隔的来源列表。来源可以是关键字,如'self'、'unsafe-inline'、'unsafe-eval',或URL,或nonce/哈希。

分步指南:部署CSP而不破坏网站

按照以下步骤安全地推出CSP。

  1. 从仅报告策略开始。 使用Content-Security-Policy-Report-Only头而不是强制执行的头。这样你可以看到哪些内容会被阻止,而不会实际阻止它们。
  2. 设置宽松策略。 从类似default-src 'self' 'unsafe-inline' 'unsafe-eval' https:开始,允许大多数内容。这可以最大限度地减少破坏。
  3. 收集违规报告。 将report-uri配置到一个记录违规的端点。查看这些报告以识别被阻止的资源。
  4. 修复违规。 更新代码以避免内联脚本/样式,或添加nonce/哈希。将外部资源移动到允许的域。
  5. 逐步收紧策略。 在重构后移除'unsafe-inline'和'unsafe-eval'。缩小允许的域。
  6. 切换到强制模式。 一旦报告显示没有意外阻止,将头改为Content-Security-Policy(不带-Report-Only)。
  7. 持续监控。 保持报告端点活跃以捕捉新问题。

这种增量方法确保你在提高安全性的同时不会破坏网站。

为内联脚本使用Nonce和哈希

内联脚本是CSP破坏的常见原因。不要允许'unsafe-inline',而是使用nonce(一次性数字)或哈希。

Nonce方法: 为每个请求生成一个随机nonce,将其添加到CSP头中,并包含在脚本标签中。

Content-Security-Policy: script-src 'nonce-abc123'
<script nonce="abc123">...</script>

哈希方法: 计算内联脚本的SHA哈希并将其添加到策略中。

Content-Security-Policy: script-src 'sha256-xyz...'

哈希最适合不经常变化的静态内联脚本。Nonce更适合动态内容。

对于样式,你也可以使用nonce或哈希,但请注意,带nonce的style-src不涵盖内联样式属性(例如style="...")。对于这些,你需要'unsafe-inline'或重构为类。

常见CSP指令及其影响

指令 控制内容 常见来源
default-src 所有资源类型的回退 'self', https:
script-src JavaScript来源 'self', 'nonce-...', 'sha256-...', https://cdn.com
style-src CSS来源 'self', 'unsafe-inline', 'nonce-...'
img-src 图片来源 'self', data:, https://images.com
connect-src AJAX、WebSocket、fetch 'self', https://api.com
font-src Web字体 'self', https://fonts.gstatic.com
frame-src Iframes 'self', https://youtube.com

在构建策略时,将此表作为快速参考。

测试和监控你的CSP

在强制执行之前,彻底测试。使用浏览器开发者工具:Console标签将CSP违规显示为错误。Network标签显示CSP头。

对于自动化测试,考虑使用Google的CSP Evaluator(在线)或csp_evaluator npm包等工具。这些有助于识别弱策略。

设置一个报告端点以在生产中收集违规。你可以使用Report URI等服务,或构建自己的端点记录到文件或数据库。定期分析报告以捕捉新问题。

记住:CSP不是银弹。它只是一层防御。将其与输入验证、输出编码和其他安全最佳实践相结合。

常见问题

Content-Security-Policy和Content-Security-Policy-Report-Only有什么区别?

强制头(Content-Security-Policy)会阻止违规。仅报告头(Content-Security-Policy-Report-Only)仅报告违规而不阻止,允许你安全地测试策略。

我可以在CSP中使用像onclick这样的内联事件处理程序吗?

不可以,除非你使用'unsafe-inline'(不推荐)或重构为使用addEventListener,否则内联事件处理程序会被CSP阻止。为了更好的安全性,避免内联事件处理程序。

如何使用CSP允许Google Analytics?

将Google Analytics域添加到你的script-src和connect-src指令中。例如:script-src 'self' https://www.googletagmanager.com; connect-src 'self' https://www.google-analytics.com。查看Google的文档以了解最新要求。

部署CSP不必是一个痛苦的过程。通过渐进的方法,你可以保护用户免受XSS和其他攻击,而不会中断网站。从仅报告模式开始,修复违规,并随着时间的推移收紧策略。

如果你需要快速格式化或验证CSP报告的JSON配置文件,请尝试我们的JSON Formatter来美化和调试你的JSON数据。