一、CPS简介
Content-Security-Policy(CSP,内容安全策略)是一种由浏览器实施的安全机制,用于防止跨站脚本攻击(XSS) 、数据注入攻击 和点击劫持等常见 Web 安全威胁。
它通过白名单机制控制网页可以加载和执行哪些资源,从而有效减少恶意代码的执行机会。
二、核心作用
1、防止 XSS 攻击
禁止内联脚本执行,限制脚本只能从可信域名加载,即使攻击者注入恶意脚本,也无法执行。
2、控制资源加载来源
可限制图片、样式、字体、iframe、Ajax 请求等资源的来源,防止加载恶意内容。
3、防止数据泄露和点击劫持
通过限制表单提交目标、iframe 嵌入来源等方式,增强页面行为的安全性。
三、CSP 的设置方式
1、通过 HTTP 响应头设置(推荐)
示例:
Content-Security-Policy: script-src 'self'; object-src 'none'; img-src * data:;
含义:
-
只允许加载当前域名的脚本;
-
禁止加载任何
<object>
标签资源; -
图片可从任意来源加载,包括 data URI。
2、通过 HTML <meta>
标签设置
示例:
<meta http-equiv="Content-Security-Policy" content="script-src 'self'; style-src cdn.example.org;">
四、配置说明
1、常用指令(Directive)说明
指令 | 功能 |
---|---|
default-src |
默认资源加载策略(其他未指定指令的 fallback) |
script-src |
控制 JavaScript 的来源 |
style-src |
控制 CSS 的来源 |
img-src |
控制图片的来源 |
connect-src |
控制 Ajax、WebSocket 等连接的目标 |
frame-src |
控制 iframe 的来源 |
form-action |
限制表单提交的目标地址 |
report-uri / report-to |
设置违规报告接收地址,用于安全监控 |
2、指令值(Source)说明
值 | 含义 |
---|---|
'self' |
只允许同源资源 |
'none' |
禁止任何资源 |
'unsafe-inline' |
允许内联脚本/样式(⚠️降低安全性) |
'unsafe-eval' |
允许使用 eval() 等动态执行代码(⚠️高风险) |
https://example.com |
允许指定域名 |
nonce-<随机值> |
仅允许带有匹配 nonce 属性的脚本 |
sha256-<哈希值> |
仅允许哈希匹配的内联脚本 |
五、注意事项
1、生产前必做,仅报告模式
先在 Content-Security-Policy-Report-Only 头里跑 1-3 天,只记录不阻断:
nginx配置如下:
add_header Content-Security-Policy-Report-Only
"default-src 'self'; script-src 'self' https://static.xxx.com; report-uri /csp-report" always;
观察 /csp-report 接收到的 JSON 违规日志,确认无合法资源被误杀后,再改成正式的 Content-Security-Policy 头 。
2、script-src 没有nonce/hash 不能使用 'unsafe-inline'
否则会导致所有内联 <script>alert(1)</script> 和 DOM 级 element.onclick = ... 放行。
攻击示例:
#请求
https://victim.com/search?q=
<script>alert(document.cookie)</script>
#返回结果
搜索关键词:<script>alert(document.cookie)</script>
错误配置示例:
add_header Content-Security-Policy "
default-src 'self';
script-src 'self' data:;
3、script-src 不能允许 data
否则会导致 data:text/javascript,alert(1) 这种 Base64 内嵌脚本会被执行。
攻击者只需注入 <script src="data:text/javascript,..."> 即可完成 XSS,完全绕过域名白名单。
错误配置示例:
add_header Content-Security-Policy "
default-src 'self';
script-src 'self' 'unsafe-inline';
六、服务器配置示例
1、NGINX配置示例
在 server {} 块里加一行:
server {
listen 80;
server_name example.com;
# 全部响应都附加 CSP
add_header Content-Security-Policy "
default-src 'self';
script-src 'self' https://cdn.jsdelivr.net;
style-src 'self' https://fonts.googleapis.com;
img-src 'self' data: https:;
font-src 'self' https://fonts.gstatic.com;
object-src 'none';
frame-ancestors 'self';
upgrade-insecure-requests;
" always;
location / {
proxy_pass http://127.0.0.1:8080;
# 其他代理头省略
}
}
重启 Nginx 后,所有 HTML 响应都会带上该头字段 。
2、Tomcat配置示例
修改 conf/web.xml
,追加全局过滤器:
<filter>
<filter-name>HttpHeaderSecurityFilter</filter-name>
<filter-class>org.apache.catalina.filters.HttpHeaderSecurityFilter</filter-class>
<init-param>
<param-name>content-security-policy</param-name>
<param-value>
default-src 'self';
script-src 'self' 'unsafe-inline';
style-src 'self' 'unsafe-inline';
img-src 'self' data:;
object-src 'none';
frame-ancestors 'self';
</param-value>
</init-param>
</filter>
<filter-mapping>
<filter-name>HttpHeaderSecurityFilter</filter-name>
<url-pattern>/*</url-pattern>
</filter-mapping>
重启 Tomcat 后,所有响应自动携带 CSP 头
3、Spring Boot 示例
public class SecurityConfig {
@Bean
SecurityFilterChain filterChain(HttpSecurity http) throws Exception {
http
.headers(headers -> headers
.contentSecurityPolicy(csp -> csp.policyDirectives(
"default-src 'self'; " +
"script-src 'self' https://cdn.jsdelivr.net; " +
"style-src 'self' https://fonts.googleapis.com; " +
"img-src 'self' data: https:; " +
"font-src 'self' https://fonts.gstatic.com; " +
"object-src 'none'; " +
"frame-ancestors 'self'; " +
"upgrade-insecure-requests;")));
return http.build();
}
}
Spring Boot 3.x 可用,启动后观察响应头已含 Content-Security-Policy