浏览器 Web 安全基础系列
CSP 与浏览器安全响应头(当前篇)
浏览器安全响应头不是“加得越多越安全”,而是服务端明确告诉浏览器:哪些脚本可执行、页面能否被嵌入、是否强制 HTTPS、Referer 发多少信息。配置正确可以显著缩小攻击面,配置错误也可能导致页面不可用。

CSP 解决什么问题
Content Security Policy 通过白名单或 nonce/hash 限制资源加载和脚本执行。一个基础策略:
Content-Security-Policy: default-src 'self'; script-src 'self'; object-src 'none'; base-uri 'self'; frame-ancestors 'none'
含义:
default-src 'self':未单独声明的资源默认只允许本站;script-src 'self':脚本只从本站加载;object-src 'none':禁止插件对象;base-uri 'self':限制<base>;frame-ancestors 'none':禁止页面被 iframe 嵌入。
为什么不建议 unsafe-inline
很多旧项目为了让内联脚本继续运行,会配置:
script-src 'self' 'unsafe-inline'
这会允许大量内联脚本执行,削弱 CSP 对 XSS 的防护。更推荐 nonce:
Content-Security-Policy: script-src 'self' 'nonce-r4nd0m'
页面中的合法脚本带相同 nonce:
<script nonce="r4nd0m">
bootstrapApp();
</script>
nonce 应每个响应随机生成,不能写死在模板中。
Express 伪代码:
app.use((req, res, next) => {
res.locals.nonce = crypto.randomBytes(16).toString('base64');
res.setHeader('Content-Security-Policy',
`default-src 'self'; script-src 'self' 'nonce-${res.locals.nonce}'; object-src 'none'`
);
next();
});
Report-Only 先观察
直接启用严格 CSP 可能阻断现有统计脚本、内联样式和第三方组件。可以先使用:
Content-Security-Policy-Report-Only: ...
浏览器记录违规但不阻断。根据报告清理依赖,再切换到正式 CSP。不要为了消除报告无限扩大白名单。
常用安全响应头

Strict-Transport-Security
强制后续访问使用 HTTPS:
Strict-Transport-Security: max-age=31536000; includeSubDomains
X-Content-Type-Options
X-Content-Type-Options: nosniff
要求浏览器尊重声明的 MIME 类型,降低把非脚本内容猜测为脚本执行的风险。服务端同时要正确返回 Content-Type。
Referrer-Policy
Referrer-Policy: strict-origin-when-cross-origin
控制 Referer 发送范围:同源可发送更多信息,跨源通常只发送 Origin,HTTPS 降级到 HTTP 时不发送。
敏感 Token 不应放进 URL,即使配置 Referrer-Policy,也不该依赖它掩盖设计问题。
Permissions-Policy
限制页面和嵌入内容使用摄像头、麦克风、定位等功能:
Permissions-Policy: camera=(), microphone=(), geolocation=(self)
X-Frame-Options
旧式 iframe 防护:
X-Frame-Options: DENY
现代项目优先使用 CSP frame-ancestors,也可同时保留 X-Frame-Options 兼容旧客户端。
Helmet 是否一装就完事
Express 常用 Helmet 设置多种安全头:
app.use(helmet({
contentSecurityPolicy: {
directives: {
defaultSrc: ["'self'"],
scriptSrc: ["'self'"]
}
}
}));
它能减少漏配,但 CSP 白名单、跨域资源、iframe 和业务需求仍要按项目设计。默认配置不是对所有系统都完美。
CSP 不能替代 XSS 修复
如果 CSP 允许大量第三方域名、unsafe-inline 或危险脚本端点,攻击者仍可能利用。即使严格 CSP 阻断某段脚本,漏洞数据还可能破坏页面结构或进行钓鱼。
正确顺序:
安全输出与清洗
→ 减少危险 API
→ CSP 限制脚本执行
→ 监控违规报告
常见误区
把所有 CDN 域名加入 script-src
第三方脚本一旦被篡改,仍拥有页面权限。应固定必要来源,并配合 SRI 或自托管。
用元标签配置所有安全头
部分策略可用 <meta>,但 HSTS、X-Frame-Options 等必须通过 HTTP 响应头;CSP 某些能力在 meta 中也有限制。
复制一份网上 CSP 直接上线
CSP 与资源加载结构高度相关,应通过 Report-Only 和浏览器开发者工具逐步收紧。
小结
安全响应头是浏览器端纵深防御:CSP 控制可执行内容,HSTS 强制 HTTPS,nosniff 限制 MIME 猜测,Referrer-Policy 减少来源泄露,Permissions-Policy 限制敏感能力。它们必须建立在正确业务代码之上。
参考资料
https://developer.mozilla.org/en-US/docs/Web/HTTP/Guides/CSP
https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Headers/Content-Security-Policy
https://cheatsheetseries.owasp.org/cheatsheets/Content_Security_Policy_Cheat_Sheet.html
https://developer.mozilla.org/en-US/docs/Web/HTTP/Reference/Headers/X-Content-Type-Options
CSP 与浏览器安全响应头:给 Web 应用增加第二道防线
https://lautung.com/archives/web-security-09-csp-headers
评论