如何发送 Reporting API 报告跨域 (Report-To) 标头

Posted

技术标签:

【中文标题】如何发送 Reporting API 报告跨域 (Report-To) 标头【英文标题】:How to send Reporting API reports cross-origin (Report-To) header 【发布时间】:2022-01-12 06:39:39 【问题描述】:

我有一个用于收集内容安全策略 (CSP) 违规报告的 API。现在report-urireport-to 指令取代,我打算使用它。但是,我无法获得跨域报告。我试过使用cors 包。但仍然无法得到报告。

我在客户端来源(example-1.com)上设置的标题是:

res.setHeader(
    'Report-To',
    '"group":"csp-endpoint","max_age":10886400,"endpoints":["url": "https://example-2.com/csp-report"]'
);

在 CSP 中,report-to 值设置为 csp-endpoint(这是在同源上工作)

在服务器端(example-2.com),存在以下代码(Express.js 服务器):

app.use(
    '/csp-report',
    express.json(
        type: [
            'application/json',
            'application/csp-report',
            'application/reports+json'
        ]
    )
);

app.use('/csp-report', cors()) // Using cors npm package

app.post('/csp-report', (req, res) => 
    res.setHeader('Access-Control-Expose-Headers', '*, Authorization');
    console.log(req.headers);
    console.log('CSP Violation Timestamp : ' + new Date().getTime());
    console.log(req.body);
    res.status(204).send();
);

我没有收到来自跨域的报告。请把我当作初学者,让我知道我在哪里犯错。谢谢。

【问题讨论】:

【参考方案1】:

您的代码似乎是正确的,但目前在 Chrome/Chromium 的 Reporting API 的 CORS 实现中存在错误,这可能会导致您的问题。见Chromium issue #1152867。该错误的要点是此处使用的 CORS 实现要求响应中存在 Access-Control-Allow-Methods: POST 标头,这不符合 CORS 规范,因为 POST 是一种“简单”方法。

如果您能够修改服务器上的 CORS 实现,则可以将其修改为始终在 OPTIONS 响应中包含 Access-Control-Allow-Methods: POST 标头,这应该可以解决该错误。

否则,您必须要么不使用跨域报告请求,要么回退到仅使用已弃用的 Report-Uri 指令,直到修复发布。后者应该不是太大的问题,因为 Firefox 和 Safari 还不支持新的 Report-To 标头。

【讨论】:

这就是我要找的。非常感谢。【参考方案2】:

当配置了report-to 指令时,CSP 报告将使用Reporting API 发送报告。在这种情况下,浏览器将要求 CORS 用于跨域报告,并且您的服务器可能未正确配置为在该 URL 上协商 CORS。 (我不知道您正在使用的 npm 包的详细信息,但这是我的怀疑)。

浏览器会发送表单的飞行前请求:

OPTIONS /csp-report HTTP/1.1
Access-Control-Request-Headers: content-type
Access-Control-Request-Method: POST
Origin: example-1.com

您的服务器需要响应如下内容:

200 OK HTTP/1.1
Access-Control-Allow-Headers: content-type
Access-Control-Allow-Methods: POST
Access-Control-Allow-Origin: example.com
Access-Control-Max-Age: 3600

如果发生这种情况,则会发送第二个请求(带有实际报告)。

Chrome NetLog viewer 可用于调试此类问题。

此外,最新版本的 Chrome 在 DevTools for Reporting 中提供实验性支持。您应该能够看到已配置的端点以及已排队的报告。 (Chrome 96说明:打开devtools,点击齿轮图标进行设置,在“experiments”下有一个标签为“Enable Reporting API panel in the Application panel”的选项)

【讨论】:

我允许这些标题。它仍然无法正常工作。此外,NetLog 查看器只是显示它失败了。它没有显示它看起来的原因。【参考方案3】:

CSP 报告 API 不是 CORS 的主题,因为没有从服务器加载任何资源。浏览器只是发送一个报告,并不期望来自 CSP 报告 API 的任何标题/响应。为了显示这一点,您返回 204 No content 标头,这样浏览器就不会期待响应。

你为什么认为你有 CORS 问题? 当你通过 Cloudflare.com 代理站点时,它会在所有页面中注入带有 CF 的 NEL/Report-to(与 CSP/Report-to 相同)标头没有任何 CORS 问题的自己的域: 我已经为 report-uri 实现了很多端点,并且从未遇到任何 CORS 问题。

请注意,report-uri 已过时,取而代之的是 report-to 指令,但浏览器不支持 report-to,Chrome 除外。

当您出于测试目的模拟发送报告时,请勿使用普通的 ajax POST 请求 - 它受 CORS 约束。 模拟发送真实报告,在第三方域上生成一个页面:

<script>alert('inline success')</script>

并与 CSP 标头一起发送:

Content-Security-Policy: "default-src 'report-sample' report-uri https://your_reporting_api.com/endpoint;"

在调试时,使用report-uri 而不是report-to 更容易。

【讨论】:

我正在返回 204 标头,但它似乎仍然不适用于其他来源。它只会成功发送相同来源的报告。 我已经用一些相关信息更新了答案。我的问题仍然有效:您为什么认为您有 CORS 问题? 请注意,您还可以使用 Fiddler 来监视错误报告,或配置 NetLog 捕获:textslashplain.com/2020/01/17/… 并查看查看器中的“报告”选项卡netlog-viewer.appspot.com/#import @granty 查看此链接:developers.google.com/web/updates/2018/09/reportingapi。这清楚地表明Note: If your endpoint URL lives on a different origin than your site, the endpoint should support CORs preflight requests. (e.g. Access-Control-Allow-Origin: *; Access-Control-Allow-Methods: GET,PUT,POST,DELETE,OPTIONS; Access-Control-Allow-Headers: Content-Type, Authorization, Content-Length, X-Requested-With @EricLaw 我尝试了 NetLog 捕获。但是,它只显示请求失败。它没有显示发生了什么错误。

以上是关于如何发送 Reporting API 报告跨域 (Report-To) 标头的主要内容,如果未能解决你的问题,请参考以下文章

Google Analytics Reporting Api - PHP:添加用户帐户

PHP中如何设置error_reporting错误报告级别

PHP中如何设置error_reporting错误报告级别

PHP中如何设置error_reporting错误报告级别

以 XML/JSON 格式返回 Google Analytics Reporting API 结果

如何在 SQL Server Reporting Services 2008 中复制报表