CSP 的 report-to 指令怎么配置才能真正上报违规日志?
我在项目里加了 Content-Security-Policy,想用 report-to 把违规信息发到自己的接口,但试了好几次都没收到上报。是不是我配置错了?
这是我的响应头设置:
Content-Security-Policy: default-src 'self'; report-to csp-endpoint
Report-To: { "group": "csp-endpoint", "endpoints": [{ "url": "https://mydomain.com/csp-report" }], "include_subdomains": true }
浏览器控制台也没报错,但就是没看到任何请求发到 /csp-report,到底哪里出问题了?
report-to指令和Report-To头需要确保正确无误。你这里看起来基本对了,但是有几个细节要注意。1.
report-to指令里的csp-endpoint要和Report-To头里的group对应上,这个你已经做对了。2.
Report-To头的格式是 JSON 字符串,但是 HTTP 响应头里的 JSON 字符串不能有空格。你需要去掉所有的空格,让整个 JSON 成一个紧凑的字符串。你可以试试把这个
Report-To头改成这样:改完之后,调试看看是否会有请求发送到你的
/csp-report接口。如果还是没有,可能需要检查一下服务器端的日志,确认是否接收到了请求,或者是网络问题导致请求没有到达服务器。另外,确保你的 CSP 策略确实会触发违规情况,这样才能生成报告。可以尝试在页面里故意加载一个外部脚本或者图片,看看是否会触发报告。
问题分析
你的响应头是这样的:
但 Report-To 头它不是一个 JSON 对象,而是一个 JSON 数组。浏览器会把它当作字符串解析,根本不认。
正确的写法
把整个 JSON 用方括号包起来,变成数组:
注意几点:
- 最外层是方括号
[],不是花括号{}- 整个头是一个字符串值,不需要再套一层引号
-
report-to csp-endpoint这个指令的值要跟 group 名字对应上顺带一说
如果你想兼容性更好,可以用
report-uri代替,这是 CSP 1.0 就有的,浏览器支持更广:这两个不冲突,可以同时写,浏览器会选自己支持的方式上报。
验证方法
配置改好之后,你得真的触发一个违规才能看到请求。比如在页面上加一个外链图片:
因为
default-src 'self'不允许加载外部图片,这就会触发一次 CSP 违规上报,浏览器会向你的 /csp-report 发送 POST 请求。收到的 JSON 大概长这样:
常见坑再提一下
1. 接口必须是 HTTPS,除非你是 localhost
2. 接口要返回 2xx,不然浏览器当发送失败
3. 某些浏览器(比如 Safari)对 report-to 支持不太好,用 report-uri 更稳
你先改一下 Report-To 头试试,应该就能收到了。