CSP报告端点配置后收不到任何报告怎么办?
我在本地测试Content-Security-Policy时设置了report-uri,但控制台有违反记录却收不到报告,到底是哪里出问题了?
按照教程配置了CSP头:Content-Security-Policy: default-src 'self'; report-uri /csp-report,然后用express搭了接收端点:
app.post('/csp-report', (req, res) => {
console.log('收到CSP报告!', req.body);
res.sendStatus(204);
});
用浏览器访问页面时故意触发违反策略的请求(比如加载外部图片),控制台确实显示CSP violation警告,但服务器端口完全没有收到POST请求。已经用curl测试过端点能正常响应,防火墙也放行了端口,这到底是配置漏了什么步骤?
1. 首先确认你是不是用了report-uri而不是report-to。report-uri是旧版规范,现在浏览器更倾向用report-to,但实际测试发现很多浏览器对report-uri支持更好。可以试试改成这样:
Content-Security-Policy: default-src 'self'; report-uri /csp-report2. 确保你的端点地址是完整的绝对路径,本地开发时经常漏掉这个。比如:
report-uri http://localhost:3000/csp-report3. 检查你的中间件有没有正确处理JSON请求体。express默认不解析JSON,要加个body-parser:
4. 还有个坑爹的情况:某些浏览器只对
Content-Security-Policy-Report-Only头发送报告。你可以先改成这个头测试下。我上次就是被第3点坑了,没加body-parser导致请求体没解析,看起来像是没收到请求。建议你先用抓包工具看看请求到底发出来没,有时候是后端处理的问题而不是CSP配置问题。
首先确认一下浏览器是否支持report-uri,现在很多现代浏览器更推荐使用report-to而不是report-uri,因为report-to可以支持更复杂的配置。如果你用的是较新的浏览器,建议把report-uri换成report-to试试。比如这样配置:
Content-Security-Policy: default-src 'self'; report-to groupname;
然后需要在HTTP头部加上Report-To字段,类似这样:
Report-To: {"group":"groupname","max_age":3600,"endpoints":[{"url":"https://yourdomain.com/csp-report"}]}
另外需要注意的一点是,很多浏览器对report-uri或者report-to的URL有同源限制,也就是说你设置的/csp-report路径必须和页面是同一个域名。如果前端页面是在localhost下访问的,那么接收端也得是localhost,不能用127.0.0.1或者内网IP,否则浏览器可能会直接忽略这个配置。
还有一种可能是CSP策略本身的问题,有些违反行为浏览器不会发送报告,比如某些静态资源的加载失败。你可以试着用更宽松的策略来测试,比如把default-src改成允许所有资源,再故意触发违反。
最后说个容易被忽略的地方,express默认的body-parser可能没法正确解析CSP报告的JSON数据,你需要确保中间件能处理application/csp-report这种Content-Type。可以在代码里加上这行:
app.use(express.json({type: ['application/json', 'application/csp-report']}));
这样应该就能正常收到报告了。我之前也遇到过类似的坑,折腾了好久才发现是content-type的问题,浏览器发过来的格式跟普通的json不太一样。