使用 Reporting API 监控 Web 应用

您可以使用 Reporting API 监控违规问题、已弃用的 API 调用等。

Maud Nalpas
Maud Nalpas

有些错误只发生在生产环境中。您无法在本地或直播期间看到这些消息 因为真实用户真实网络真实设备 改变游戏。Reporting API 可帮助捕捉其中一些错误,如 视为违规,或者已弃用且即将弃用的 API 并将这些调用传输到您的 。

它可让您通过 HTTP 标头声明要监控的内容, 由浏览器运行。

设置 Reporting API 后,当用户遇到 您就会知道这些类型的错误,以便解决这些问题。

本文介绍此 API 的功能和使用方法。现在就开始吧!

演示和代码

从以下时间开始查看 Reporting API 的实际应用: Chrome 96 及更高版本 (Chrome Beta 版或 Canary 版)。

概览

<ph type="x-smartling-placeholder">
</ph> 总结了从报告生成到开发者访问报告的各个步骤的示意图 <ph type="x-smartling-placeholder">
</ph> 如何生成报告和发送报告。

我们假设您的网站 (site.example) 同时设置了内容安全政策和文档政策。不知道这些方法有什么用?没关系,您仍然处于 能够理解这个示例。

您决定监控自己的网站,以便了解您的网站在哪些情况下违反了这些政策,但这还因为一个原因: 您需要关注代码库可能正在使用的已废弃或即将弃用的 API。

为此,您可以配置 Reporting-Endpoints 标头,并映射这些端点 根据需要通过政策中的 report-to 指令指定该目录。

Reporting-Endpoints: main-endpoint="https://reports.example/main", default="https://reports.example/default"
# Content-Security-Policy violations and Document-Policy violations
# will be sent to main-endpoint
Content-Security-Policy: script-src 'self'; object-src 'none'; report-to main-endpoint;
Document-Policy: document-write=?0; report-to=main-endpoint;
# Deprecation reports don't need an explicit endpoint because
# these reports are always sent to the `default` endpoint

出现了不可预见的情况, 用户。

违规行为示例

index.html

<script src="script.js"></script>
<!-- CSP VIOLATION: Try to load a script that's forbidden as per the Content-Security-Policy -->
<script src="https://example.com/script.js"></script>

script.js,加载者:index.html

// DOCUMENT-POLICY VIOLATION: Attempt to use document.write despite the document policy
try {
  document.write('<h1>hi</h1>');
} catch (e) {
  console.log(e);
}
// DEPRECATION: Call a deprecated API
const webkitStorageInfo = window.webkitStorageInfo;

浏览器生成 CSP 违规报告、文档违规报告以及弃用 来找出这些问题的报告

在短暂的延迟(最多一分钟)后,浏览器会将报告发送到 此违规类型配置的端点。报告会发送到 带外 (而不是由您的服务器或您的网站进行)。

端点接收这些报告。

现在,您可以访问这些端点上的报告并监控出了什么问题。 您已准备好开始排查影响用户的问题。

示例报告

{
  "age": 2,
  "body": {
    "blockedURL": "https://site2.example/script.js",
    "disposition": "enforce",
    "documentURL": "https://site.example",
    "effectiveDirective": "script-src-elem",
    "originalPolicy": "script-src 'self'; object-src 'none'; report-to main-endpoint;",
    "referrer": "https://site.example",
    "sample": "",
    "statusCode": 200
  },
  "type": "csp-violation",
  "url": "https://site.example",
  "user_agent": "Mozilla/5.0... Chrome/92.0.4504.0"
}

用例和报告类型

通过配置 Reporting API,您可以监控多种值得关注的警告或问题 出现的所有问题

报告类型 生成报告的情况示例
CSP 违规行为(仅限级别 3) 您在自己的一个网页上设置了Content-Security-Policy (CSP),但该网页正尝试加载您的 CSP 不允许使用的脚本。
违反 COOP 您已在网页上设置了 Cross-Origin-Opener-Policy,但跨源窗口正尝试与文档直接互动。
违反 COEP 您在某网页上设置了 Cross-Origin-Embedder-Policy,但该文档包含未选择让跨源文档加载的跨源 iframe。
违反文档政策 该网页的某项文档政策禁止使用 document.write,但脚本会尝试调用 document.write
违反权限政策 该页面包含一个禁止使用麦克风的权限政策,以及一个请求音频输入的脚本。
弃用警告 网页使用的 API 已弃用或即将弃用;它可以直接调用它,也可以通过顶级第三方脚本调用它。
干预 出于安全、性能或用户体验方面的原因,网页正在尝试执行浏览器决定不认可的操作。Chrome 中的示例:网页在慢速网络上使用 document.write,或者在用户尚未互动过的跨源帧中调用 navigator.vibrate
崩溃 在您的网站打开时,浏览器崩溃。

报告

报告的外观是怎样的?

浏览器会向您已配置的端点发送报告。它会发送如下所示的请求:

POST
Content-Type: application/reports+json

这些请求的负载是一个报告列表。

报告列表示例

[
  {
    "age": 420,
    "body": {
      "columnNumber": 12,
      "disposition": "enforce",
      "lineNumber": 11,
      "message": "Document policy violation: document-write is not allowed in this document.",
      "policyId": "document-write",
      "sourceFile": "https://site.example/script.js"
    },
    "type": "document-policy-violation",
    "url": "https://site.example/",
    "user_agent": "Mozilla/5.0... Chrome/92.0.4504.0"
  },
  {
    "age": 510,
    "body": {
      "blockedURL": "https://site.example/img.jpg",
      "destination": "image",
      "disposition": "enforce",
      "type": "corp"
    },
    "type": "coep",
    "url": "https://dummy.example/",
    "user_agent": "Mozilla/5.0... Chrome/92.0.4504.0"
  }
]

以下是您可以在各种报告中找到的数据:

字段 说明
age 报告的时间戳与当前时间之间的毫秒数。
body 实际报告数据,已序列化为 JSON 字符串。报告的 body 中包含的字段由报告的 type 确定。⚠️ 不同类型的报告具有不同的正文。 如需查看每种报告类型的确切正文,请访问演示报告端点 ,并按照说明生成示例报告。
type 报告类型,例如 csp-violationcoep
url 生成报告的文档或工作器的地址。系统会从此网址中删除用户名、密码和片段等敏感数据。
user_agent 生成报告的请求的 User-Agent 标头。

经认证的报告

与生成报告的网页具有相同来源的报告端点会接收凭据 (Cookie)。

凭据可提供有关报告的其他有用背景信息;用于 例如,指定用户的账号是始终如一地触发错误, 在其他网页上执行的操作会触发此页上的报告。

浏览器何时以及如何发送报告?

报告会从您的网站带外发送:浏览器会控制何时 它们会发送到已配置的端点。此外,您也无法控制 浏览器发送报告;它会自动捕获数据,将其加入队列, 确定合适的时间

这意味着,使用 Reporting API 时几乎没有性能问题。

报告会延迟发送(最长可达一分钟),以提高批量发送报告的几率。 这能在一定程度上考虑用户的网络连接,从而节省带宽, 非常重要如果浏览器忙于处理优先级更高的任务,也会延迟递送 或者用户使用的是速度缓慢和/或拥塞的网络。

第三方和第一方问题

系统会发送由于您的网页发生违规行为或弃用情况而生成的报告 您已配置的端点。这包括第三方脚本的违规行为 您的网页上所运行的广告素材

您网页中嵌入的跨源 iframe 中出现的违规或弃用情况将会导致 不会向您的端点报告(至少默认情况下不会)。iframe 可以设置自己的 甚至向您网站的(即第一方的)报告服务生成报告;不过已经结束了 访问加框网站。另请注意,大多数报告仅在用户违反网页政策时才生成报告, 并且您的网页政策与 iframe 政策不同。

弃用情况示例

<ph type="x-smartling-placeholder">
</ph> 如果您的网页上设置了 Reporting-Endpoint 标头:您的网页上运行的第三方脚本调用的已弃用 API 会向您的端点报告。系统不会向您的端点报告由嵌入您网页中的 iframe 调用的已弃用 API。仅当 iframe 服务器设置了 Reporting-Endpoint 时,系统才会生成弃用报告,并且系统会将此报告发送到 iframe 服务器已设置的任意端点。 <ph type="x-smartling-placeholder">
</ph> 如果您的网页上设置了 Reporting-Endpoint 标头:您的网页上运行的第三方脚本调用的已弃用 API 会向您的端点报告。系统不会向您的端点报告由嵌入您网页中的 iframe 调用的已弃用 API。仅当 iframe 服务器设置了 Reporting-Endpoint 时,系统才会生成弃用报告,并且系统会将此报告发送到 iframe 服务器已设置的任意端点。

浏览器支持

下表总结了浏览器对 Reporting API v1 的支持情况(使用 Reporting-Endpoints 标头。浏览器对 Reporting API v0(Report-To 标头)的支持是 相同的,只不过有一种报告类型:新 Reporting API 不支持网络错误日志记录。 如需了解详情,请参阅迁移指南

报告类型 Chrome iOS 版 Chrome Safari Firefox Edge
内容安全政策违规(仅限 3 级)* ✔ 是 ✔ 是 ✔ 是 ✘ 否 ✔ 是
网络错误日志记录 ✘ 否 ✘ 否 ✘ 否 ✘ 否 ✘ 否
违反 COOP/COEP ✔ 是 ✘ 否 ✔ 是 ✘ 否 ✔ 是
所有其他类型的:违反文档政策、弃用、干预、崩溃 ✔ 是 ✘ 否 ✘ 否 ✘ 否 ✔ 是

下表仅总结了对带有新 Reporting-Endpoints 标头的 report-to 的支持。如果您想要迁移到 Reporting-Endpoints,请阅读 CSP 报告迁移提示

使用 Reporting API

决定将报告发送到何处

您有两种选择:

  • 将报告发送到现有的报告收集器服务。
  • 将报告发送给您自己构建和运营的报告收集器。

方法 1:使用现有的报告收集器服务

报告收集器服务的一些示例如下:

如果您知道其他解决方案,请提出问题告诉我们,我们会更新此博文!

选择报告收集器时,除了价格之外,还应考虑以下几点:🧐?

  • 此收集器是否支持所有报告类型?例如,并非所有报告端点解决方案 支持 COOP/COEP 报告。
  • 您是否愿意与第三方报告收集器共享您的应用的任何网址? 即使浏览器从这些网址中删除敏感信息,敏感信息也可能通过这种方式泄露。如果这听起来太危险了 运行您自己的报告端点

方法 2:构建和运行您自己的报告收集器

构建您自己的服务器来接收报告并非易事。首先,您可以创建我们的 轻量级样板文件它是使用 Express 构建的,可以接收和显示报告。

  1. 前往样板报告收集器

  2. 点击 Remix to Edit 以使项目可修改。

  3. 您现在拥有自己的克隆了!您可以根据自己的用途对其进行自定义。

如果您没有使用样板代码,而是要从零开始构建自己的服务器,请执行以下操作:

  • 检查 Content-Typeapplication/reports+jsonPOST 请求,以识别报告 发送到端点的请求。
  • 如果您的端点与您的网站位于不同的来源,请确保它支持 CORS 预检请求

方法 3:组合方法 1 和方法 2

您可能希望让某特定提供商处理某些类型的报告, 解决方案。

在这种情况下,请按如下所示设置多个端点:

Reporting-Endpoints: endpoint-1="https://reports-collector.example", endpoint-2="https://my-custom-endpoint.example"

配置 Reporting-Endpoints 标头

设置 Reporting-Endpoints 响应标头。其值必须是一个或一系列以英文逗号分隔的值 键值对:

Reporting-Endpoints: main-endpoint="https://reports.example/main", default="https://reports.example/default"

如果您要从旧版 Reporting API 迁移到新版 Reporting API,那么采用 同时设置了 Reporting-EndpointsReport-To如需了解详情,请参阅迁移指南。特别要指出的是,如果您为 Content-Security-Policy 违规行为只能通过 report-uri 指令进行,请查看 CSP 报告的迁移步骤

Reporting-Endpoints: main-endpoint="https://reports.example/main", default="https://reports.example/default"
Report-To: ...

键(端点名称)

每个键可以是您选择的名称,例如 main-endpointendpoint-1。 您可以决定为不同的报告设置不同的已命名端点 类型,例如 my-coop-endpointmy-csp-endpoint。通过这种方法 可以根据报告的类型将报告路由到不同的端点。

如果您希望收到干预弃用和/或崩溃 设置一个名为 default 的端点。

如果 Reporting-Endpoints 标头未定义 default 端点,系统将不会发送此类报告(尽管会生成此类报告)。

值(网址)

每个值都是您选择的一个网址,报告将发送到该网址。网址 取决于您在第 1 步中确定的设置。

端点网址:

示例

Reporting-Endpoints: my-coop-endpoint="https://reports.example/coop", my-csp-endpoint="https://reports.example/csp", default="https://reports.example/default"

然后,您可以使用相应政策中的每个已命名端点,或使用某个 跨所有政策的单个端点

在何处设置标题?

此 API 的 后 - 报表的范围限定为文档。这意味着,对于某个给定的 来源不同的文档,例如 site.example/page1site.example/page2,可以将报告发送到不同的端点。

为了接收有关违规行为或弃用情况的报告,您的 请将标头设置为所有响应的中间件。

下面是一个 Express 示例:

const REPORTING_ENDPOINT_BASE = 'https://report.example';
const REPORTING_ENDPOINT_MAIN = `${REPORTING_ENDPOINT_BASE}/main`;
const REPORTING_ENDPOINT_DEFAULT = `${REPORTING_ENDPOINT_BASE}/default`;

app.use(function (request, response, next) {
  // Set up the Reporting API
  response.set(
    'Reporting-Endpoints',
    `main-endpoint="${REPORTING_ENDPOINT_MAIN}", default="${REPORTING_ENDPOINT_DEFAULT}"`,
  );
  next();
});

修改政策

现在,Reporting-Endpoints 标头已配置完毕,接下来添加 report-to 指令添加到您希望收到违规通知的各个政策标头中 报告。report-to 的值应该是 配置。

您可以将多个端点用于多项政策,或使用不同的 端点。

对于每项政策,report-to 的值应该是您已配置的已命名端点之一。

弃用干预崩溃时不需要 report-to 报告。这些报告不受任何政策约束。只要 已设置 default 端点,并发送到此 default 端点。

示例

# Content-Security-Policy violations and Document-Policy violations
# will be sent to main-endpoint
Content-Security-Policy: script-src 'self'; object-src 'none'; report-to main-endpoint;
Document-Policy: document-write=?0;report-to=main-endpoint;
# Deprecation reports don't need an explicit endpoint because
# these reports are always sent to the default endpoint

示例代码

为了在上下文中查看,下面是一个使用 Express 的 Node 服务器示例 并将本文讨论的所有部分汇总到一起。其中介绍了如何 为几种不同的报告类型配置报告并显示结果。

调试报告设置

有意生成报告

设置 Reporting API 时,您可能需要故意违反 政策,检查报告是否按预期生成和发送。 查看违反政策以及存在其他不良行为的示例代码 可生成所有类型的报告,请查看相应演示

节省时间

报告可能会延迟发送(大约一分钟),这可能需要很长时间 。📲? 幸运的是,在 Chrome 中调试时,您可以使用 --short-reporting-delay,即可在报告生成后立即收到相关报告。

在终端中运行以下命令即可开启此标志:

YOUR_PATH/TO/EXECUTABLE/Chrome --short-reporting-delay

使用开发者工具

在 Chrome 中,使用开发者工具查看已发送或即将发送的报告。

截至 2021 年 10 月,此功能处于实验阶段。要使用该功能,请按以下步骤操作:

  1. 使用 Chrome 96 及更高版本(请在浏览器中输入 chrome://version 进行确认)
  2. 在 Chrome 的网址栏中输入或粘贴 chrome://flags/#enable-experimental-web-platform-features
  3. 点击已启用
  4. 重新启动浏览器。
  5. 打开 Chrome 开发者工具。
  6. 在 Chrome 开发者工具中,打开“设置”。在“实验”下,点击在以下位置启用 Reporting API 面板: “应用”面板
  7. 重新加载开发者工具。
  8. 重新加载页面。由开发者工具打开的页面生成的报告将 Chrome 开发者工具中列出应用面板的 Reporting API 下。
。 <ph type="x-smartling-placeholder">
</ph> 列出报告的开发者工具的屏幕截图
Chrome 开发者工具会显示页面上生成的报告及其状态。

报告状态

状态列会显示报告是否已成功发送。

状态 说明
Success 浏览器已发送报告,且端点返回了成功代码(200 或其他成功响应代码 2xx)。
Pending 浏览器正在尝试发送报告。
Queued 报告已生成,浏览器目前并未尝试发送报告。在以下两种情况下,报告会显示为 Queued: <ph type="x-smartling-placeholder">
    </ph>
  • 报告是新的,浏览器在尝试发送报告之前,会等待看看是否还有其他报告到达。
  • 该报告并非新报告;浏览器已尝试发送此报告但失败,且正在等待重试。
MarkedForRemoval 重试一段时间 (Queued) 后,浏览器已停止尝试发送报告,并会很快将其从要发送的报告列表中移除。

报告会在一段时间后移除,无论报告是否成功发送。

问题排查

是否未生成报告或未按预期发送到您的端点? 以下是排查此问题的一些提示。

未生成报告

开发者工具中显示的报告已正确生成。 如果预期的报告没有显示在此列表中,请执行以下操作:

  • 请查看您的政策中的 report-to。如果配置有误 系统将不会生成报告。请前往修改政策, 解决此问题。排查此问题的另一种方法是查看 Chrome 中的开发者工具控制台:如果 错误,这表示您的政策可能 已正确配置。
  • 请注意,只有为开发者工具打开的文档生成的报告才会打开 所有资源例如:如果您的网站 site1.example 嵌入了 iframe site2.example 并因此生成了报告,那么只有在您打开 iframe 中打开,然后为该窗口打开开发者工具。

生成报告,但无法发送或接收

如果您可以在开发者工具中看到报告,但端点没有收到报告,该怎么办?

  • 请务必使用短暂的延迟。您看不到报告的原因可能是 尚未发送!
  • 检查您的 Reporting-Endpoints 标头配置。如果存在问题, 正确生成的文件将无法发送。在开发者工具中,报告的状态将保持不变 Queued(如果尝试传送,可能会跳转到 Pending,然后快速恢复为 Queued )。可能会导致这种情况的一些常见错误:

  • 端点正在使用中,但未配置。示例:

包含错误的代码
 Document-Policy: document-write=?0;report-to=endpoint-1;
 Reporting-Endpoints: default="https://reports.example/default"

文档违规报告应发送到 endpoint-1,但此端点名称未在以下位置配置: Reporting-Endpoints

  • 缺少“default”端点。某些报告类型,例如弃用和干预 报告只会发送到名为 default 的端点。如需了解详情,请参阅配置 Reporting-Endpoint 标头

  • 检查政策标头语法中是否存在问题,例如缺少引号。查看详情

  • 检查您的端点是否可以处理传入请求。

    • 确保您的端点支持 CORS 预检请求。否则,设备将无法接收报告。

    • 测试端点的行为。为此,您无需生成 您可以模拟浏览器,方法是向端点发送请求,格式类似于 浏览器会发送什么内容运行以下命令:

    curl --header "Content-Type: application/reports+json" \
      --request POST \
      --data '[{"age":420,"body":{"columnNumber":12,"disposition":"enforce","lineNumber":11,"message":"Document policy violation: document-write is not allowed in this document.","policyId":"document-write","sourceFile":"https://dummy.example/script.js"},"type":"document-policy-violation","url":"https://dummy.example/","user_agent":"xxx"},{"age":510,"body":{"blockedURL":"https://dummy.example/img.jpg","destination":"image","disposition":"enforce","type":"corp"},"type":"coep","url":"https://dummy.example/","user_agent":"xxx"}]' \
      YOUR_ENDPOINT
    

    您的端点应会返回一个成功代码(200 或另一个成功响应代码 2xx)。如果没有, 其配置存在问题

仅用于报告

-Report-Only 政策标头和 Reporting-Endpoints 可搭配使用。

Reporting-Endpoints 中配置并在以下实例的 report-to 字段中指定的端点: Content-Security-PolicyCross-Origin-Embedder-PolicyCross-Origin-Opener-Policy 在违反这些政策时会收到报告。

Reporting-Endpoints 中配置的端点也可以在 report-to字段 Content-Security-Policy-Report-OnlyCross-Origin-Embedder-Policy-Report-OnlyCross-Origin-Opener-Policy-Report-Only。 他们还会在违反这些政策时收到举报。

虽然在这两种情况下都会发送报告,但 -Report-Only 标头不会强制实施 政策不会中断,也不会被阻止 报告哪些地方会出现问题或被屏蔽。

ReportingObserver

ReportingObserver JavaScript API 可以帮助您 并观察客户端警告。

ReportingObserverReporting-Endpoints 标头会生成 看起来一样,但它们的使用场景略有不同。

在以下情况下可使用 ReportingObserver

  • 您只想监控废弃和/或浏览器干预。 ReportingObserver 会显示客户端警告,例如弃用情况 但与 Reporting-Endpoints 不同的是,它不会 捕获任何其他类型的报告,例如 CSP 或 COOP/COEP 违规行为。
  • 您需要实时应对这些违规行为。ReportingObserver制造商 可以向违规事件附加回调
  • 您想向报告附加其他信息以帮助调试, (通过自定义回调实现)。

另一个区别是,ReportingObserver 仅在客户端配置: 即使您无法控制服务器端标头且无法 设置Reporting-Endpoints

深入阅读

主打图片作者:Nine Koepfer / @enka80 Unlaunch,已修改。非常感谢 Ian Clelland、Eiji Kitamura 和 Milica Mihajlija 对本文发表的评价和建议。