研发安全 | 如何用好内容安全策略(CSP)?
字数 2317 2025-08-20 18:18:23
内容安全策略(CSP)全面指南
CSP概述
内容安全策略(Content-Security-Policy, CSP)是一种重要的Web安全机制,通过服务器端注入CSP头,浏览器能够帮助用户降低XSS、点击劫持和跨站数据泄露等安全风险。
CSP本质
- 白名单制度:明确告诉客户端哪些外部资源可以加载和执行
- 浏览器执行:实现和执行全部由浏览器完成,开发者只需提供配置
- 纵深防御:即使攻击者发现漏洞,也难以成功注入恶意脚本
- 报告机制:通过态势感知和CSP报告机制可及时发现攻击行为
主要配置指令
| 指令 | 功能描述 |
|---|---|
default-src |
定义大多数资源的默认源 |
script-src |
指定允许加载和执行的脚本源 |
style-src |
指定允许加载和应用的样式表源 |
img-src |
指定允许加载的图像源 |
font-src |
指定允许加载的字体源 |
media-src |
指定允许加载的媒体资源(视频/音频)源 |
object-src |
指定允许加载的插件(如Flash)源 |
frame-src |
指定允许在iframe中加载的资源源 |
child-src |
指定允许作为子资源加载的源 |
connect-src |
指定允许进行网络连接(AJAX请求)的源 |
form-action |
指定表单提交的允许目标源 |
frame-ancestors |
指定允许嵌入当前页面的祖先页面源 |
manifest-src |
指定允许加载的Web应用程序清单源 |
worker-src |
指定允许加载的Web Workers源 |
base-uri |
指定页面中<base>标签的允许源 |
plugin-types |
指定允许加载的插件类型 |
sandbox |
为页面提供安全沙箱环境,限制脚本、表单提交等行为 |
navigate-to |
指定允许页面导航到的源 |
prefetch-src |
指定允许预加载的资源源 |
report-uri |
指定CSP违规报告发送到的URI |
report-to |
指定CSP违规报告发送到的报告端点名称 |
upgrade-insecure-requests |
指示浏览器将所有HTTP请求升级为HTTPS |
block-all-mixed-content |
阻止所有混合内容(HTTPS页面上加载HTTP资源) |
referrer |
控制发送到请求中的Referer头部 |
policy-uri |
提供指向当前策略的URI,供浏览器在需要时获取 |
CSP实施方式
1. HTTP Header方式(首选)
Content-Security-Policy: 策略
Content-Security-Policy-Report-Only: 策略
2. HTML Meta标签方式
<meta http-equiv="content-security-policy" content="策略">
<meta http-equiv="content-security-policy-report-only" content="策略">
注意:
- 如果HTTP头与Meta定义同时存在,优先采用HTTP中的定义
- 如果浏览器已为当前文档执行了CSP策略,会跳过Meta定义
- 如果meta标签缺少content属性,同样会跳过
CSP策略语法
- 多个指令之间用英文分号(
;)分割 - 多个指令值用英文空格分割
- 避免重复定义同一指令(后定义的会被忽略)
正确与错误示例
错误写法(第二个指令会被忽略):
Content-Security-Policy: script-src https://host1.com; script-src https://host2.com
正确写法:
Content-Security-Policy: script-src https://host1.com https://host2.com
CSP策略示例
- 限制所有外部资源只能从当前域名加载:
Content-Security-Policy: default-src 'self'
- 复杂策略示例:
Content-Security-Policy:
default-src https://host1.com https://host2.com;
frame-src 'none';
object-src 'none'
- 带报告功能的策略:
Content-Security-Policy:
default-src 'self';
report-uri /my_amazing_csp_report_parser;
CSP指令值说明
| 指令值 | 说明 |
|---|---|
'self' |
表示同源,只允许从当前域名加载资源 |
https://example.com |
明确指定允许加载资源的域名 |
'none' |
禁止加载任何资源 |
'unsafe-inline' |
允许内联脚本/样式(降低安全性) |
'unsafe-eval' |
允许eval等动态代码执行(降低安全性) |
'strict-dynamic' |
信任由已执行脚本动态创建的脚本 |
CSP自查表
| 指令 | 示例 | 说明 |
|---|---|---|
default-src |
default-src 'self'; |
定义大多数资源的默认允许源 |
script-src |
script-src 'self' https://cdn.com; |
指定允许加载和执行脚本的源 |
style-src |
style-src 'self' 'unsafe-inline'; |
指定允许加载的样式表源 |
最佳实践
- 从严格策略开始:初始配置尽可能严格,逐步放宽
- 使用报告模式:先使用
Content-Security-Policy-Report-Only测试策略 - 避免内联脚本:尽量不使用
'unsafe-inline' - 限制外部资源:明确指定可信的外部域名
- 定期审查:根据CSP报告定期审查和更新策略
- HTTPS优先:配合
upgrade-insecure-requests和block-all-mixed-content使用
注意事项
- CSP不是万能的,不能替代其他安全措施
- 如果攻击者控制了白名单内的可信主机,CSP可能失效
- 复杂的网站可能需要逐步实施CSP
- 某些旧版浏览器可能不完全支持所有CSP特性