使用 COOP 和 COEP 将您的网站设为“跨域隔离”

使用 COOP 和 COEP 设置跨域隔离环境,并启用 SharedArrayBuffer、performance.measureUserAgentSpecificMemory() 和高分辨率计时器等强大功能,从而提高精确度。

发布时间:2020 年 4 月 13 日,最后更新时间:2022 年 6 月 21 日

本文档介绍了如何使用这些 COOP 和 COEP。如需详细了解为何这很重要,请参阅使用 COOP 和 COEP 使您的网站“跨域隔离”。

某些 Web API 会增加边信道攻击(例如 Spectre)的风险。为了降低这种风险,浏览器提供了一种基于选择启用的隔离环境,称为跨域隔离。在跨域隔离状态下,网页将能够使用特权功能,包括:

API 说明
SharedArrayBuffer WebAssembly 线程需要此标头。此功能从 Android Chrome 88 开始提供。在网站隔离的帮助下,桌面版默认处于启用状态,但需要跨域隔离状态,并且在 Chrome 92 中默认处于停用状态。
performance.measureUserAgentSpecificMemory() 从 Chrome 89 开始提供。
performance.now(),performance.timeOrigin 在许多浏览器中可用,分辨率限制为 100 微秒或更高。通过跨域隔离,分辨率可以达到 5 微秒或更高。
在跨域隔离状态下可用的功能。

跨域隔离状态还会阻止对 document.domain 的修改。(能够更改 document.domain 允许同一网站文档之间进行通信,这被视为同源政策中的漏洞。)

如需选择启用跨域隔离状态,您需要在主文档中发送以下 HTTP 标头:

Cross-Origin-Embedder-Policy: require-corp
Cross-Origin-Opener-Policy: same-origin

这些标头会指示浏览器阻止加载未选择由跨域文档加载的资源或 iframe,并阻止跨域窗口直接与您的文档交互。这也意味着,这些跨域加载的资源需要选择启用。

您可以通过检查 self.crossOriginIsolated 来确定网页是否处于跨域隔离状态。

术语表

本文档使用了许多名称相似和缩写的术语。为了让大家更清楚地了解,我们整理了一个迷你词汇表:

使您的网站实现跨域隔离

1. 在顶级文档上设置 Cross-Origin-Opener-Policy: same-origin

通过在顶级文档上启用 COOP: same-origin,具有相同来源的窗口和从该文档打开的窗口具有单独的浏览上下文组,除非它们位于具有相同 COOP 设置的同一来源中。因此,系统会对打开的窗口强制执行隔离,并停用两个窗口之间的相互通信。

浏览上下文组是一组可以相互引用的窗口。例如,顶级文档及其使用 <iframe> 嵌入的子文档。如果网站 (https://a.example) 打开对话框窗口 (https://b.example),则打开器窗口和对话框窗口会共享相同的浏览上下文,因此它们可以使用 DOM API(例如 window.opener)相互访问。

插图:浏览内容组,其中用户正在与页面元素互动。

您可以在开发者工具中检查窗口打开工具及其打开的窗口是否位于不同的浏览上下文组中。

2. 为资源启用 CORP 或 CORS

确保网页中的所有资源都使用 CORP 或 CORS HTTP 标头加载。第四步(启用 COEP)需要执行此步骤。

根据资源的性质,您需要执行以下操作:

  • 如果预计资源仅从同源加载,请设置 Cross-Origin-Resource-Policy: same-origin 标头。
  • 如果资源预计仅从同一网站但跨源加载,请设置 Cross-Origin-Resource-Policy: same-site 标头。
  • 如果资源是从您控制的跨域加载,请尽可能设置 Cross-Origin-Resource-Policy: cross-origin 标头。
  • 对于您无法控制的跨域资源:
    • 如果资源是通过 CORS 提供的,请在加载 HTML 标记中使用 crossorigin 属性。(例如,<img src="***" crossorigin>。)
    • 请让资源所有者支持 CORS 或 CORP。
  • 对于 iframe,请遵循相同的原则并设置 Cross-Origin-Resource-Policy: cross-origin(或 same-site、same-origin,具体取决于上下文)。
  • 使用 WebWorker 加载的脚本必须从同源提供,因此您不需要 CORP 或 CORS 标头。
  • 对于使用 COEP: require-corp 提供的文档或工作器,在没有 CORS 的情况下加载的跨域子资源必须设置 Cross-Origin-Resource-Policy: cross-origin 标头,才能选择嵌入。例如,这适用于 <script>、importScripts、<link>、<video>、<iframe> 等。

iframe 中的隔离

您可以通过将 allow="cross-origin-isolated" 权限政策应用于 <iframe> 标记并满足以下条件,在 iframe 中嵌入的文档上启用跨域隔离。整个文档链(包括父框架和子框架)也必须进行跨域隔离。

3. 使用 COEP Report-Only HTTP 标头评估嵌入式资源

在完全启用 COEP 之前,您可以使用 Cross-Origin-Embedder-Policy-Report-Only 标头进行试运行,以检查该政策是否确实有效。您将收到报告,而不会屏蔽嵌入式内容。

以递归方式将此规则应用于所有文档,包括顶级文档、iframe 和工作器脚本。如需了解 Report-Only HTTP 标头,请参阅使用 Reporting API 观察问题。

4. 启用 COEP

只有在确保资源已启用 CORP 或 CORS 后,才能执行此步骤。

确认一切正常且所有资源均可成功加载后,将 Cross-Origin-Embedder-Policy-Report-Only 标头切换为具有相同值的所有文档(包括使用 iframe 和 worker 脚本嵌入的文档)的 Cross-Origin-Embedder-Policy 标头。

确定隔离是否成功

当网页处于跨域隔离状态,并且所有资源和窗口都在同一浏览上下文组中隔离时,self.crossOriginIsolated 属性会返回 true。您可以使用此 API 确定是否已成功隔离浏览上下文组并获得对 performance.measureUserAgentSpecificMemory() 等功能的访问权限。

调试问题

您可能会遇到 COOP 和 COEP 问题。您可以使用浏览器开发者工具或 Reporting API 进行调试。

使用 Chrome 开发者工具进行调试

对于在屏幕上呈现的资源(例如图片),检测 COEP 问题相当容易,因为请求会被屏蔽,并且页面应指示缺少图片。不过,对于不一定会产生视觉影响的资源(例如脚本或样式),COEP 问题可能会被忽视。对于这些情况,请使用开发者工具的“网络”面板。

如果 COEP 存在问题,您应该会在状态列中看到 (blocked:NotSameOriginAfterDefaultedToSameOriginByCoep)。

“网络”面板的“状态”列中的 COEP 问题。

然后,您可以点击相应条目以查看更多详细信息。

在“网络”面板中点击某个网络资源后,“标头”标签页中会显示 COEP 问题的详细信息。

您还可以通过应用面板确定 iframe 和对话框窗口的状态。前往左侧的“Frames”部分,然后展开“top”以查看资源结构的细分。

您可以检查 iframe 的状态,例如 SharedArrayBuffer 的可用性等。

Chrome 开发者工具 iframe 检查器。

您还可以检查对话框窗口的状态,例如是否已跨域隔离。

Chrome 开发者工具对话框窗口检查器

使用 Reporting API 观察问题

Reporting API 是另一种可用于检测各种问题的机制。您可以配置 Reporting API,以指示用户的浏览器在 COEP 阻止加载资源或 COOP 隔离对话框窗口时发送报告。自 69 版起,Chrome 就已支持 Reporting API,并将其用于各种用途,包括 COEP 和 COOP。

了解如何配置 Reporting API 并设置服务器以接收报告。

COEP 报告示例

当跨域资源被屏蔽时,COEP 报告载荷示例如下所示:

[{
  "age": 25101,
  "body": {
    "blocked-url": "https://third-party-test.example.org/check.svg?",
    "blockedURL": "https://third-party-test.example.org/check.svg?",
    "destination": "image",
    "disposition": "enforce",
    "type": "corp"
  },
  "type": "coep",
  "url": "https://cross-origin-isolation.example.com/?coep=require-corp&coop=same-origin&",
  "user_agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4249.0 Safari/537.36"
}]

COOP 报告示例

当对话框在隔离状态下打开时,COOP 报告载荷示例如下所示:

[{
  "age": 7,
  "body": {
    "disposition": "enforce",
    "effectivePolicy": "same-origin",
    "nextResponseURL": "https://third-party-test.example.org/popup?report-only&coop=same-origin&",
    "type": "navigation-from-response"
  },
  "type": "coop",
  "url": "https://cross-origin-isolation.example.com/coop?coop=same-origin&",
  "user_agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4246.0 Safari/537.36"
}]

当不同的浏览上下文组尝试相互访问时(仅在“仅报告”模式下),COOP 也会发送报告。例如,尝试 postMessage() 时的报告如下所示:

[{
  "age": 51785,
  "body": {
    "columnNumber": 18,
    "disposition": "reporting",
    "effectivePolicy": "same-origin",
    "lineNumber": 83,
    "property": "postMessage",
    "sourceFile": "https://cross-origin-isolation.example.com/popup.js",
    "type": "access-from-coop-page-to-openee"
  },
  "type": "coop",
  "url": "https://cross-origin-isolation.example.com/coop?report-only&coop=same-origin&",
  "user_agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4246.0 Safari/537.36"
},
{
  "age": 51785,
  "body": {
    "disposition": "reporting",
    "effectivePolicy": "same-origin",
    "property": "postMessage",
    "type": "access-to-coop-page-from-openee"
  },
  "type": "coop",
  "url": "https://cross-origin-isolation.example.com/coop?report-only&coop=same-origin&",
  "user_agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/87.0.4246.0 Safari/537.36"
}]

要点总结

结合使用 COOP 和 COEP HTTP 标头,使网页进入特殊的跨域隔离状态。您可以检查 self.crossOriginIsolated,以确定网页是否处于跨域隔离状态。

随着此跨域隔离状态的新功能推出,以及 DevTools 围绕 COOP 和 COEP 的进一步改进,我们将持续更新此帖子。

资源

文档更新

  • 2022 年 6 月 21 日:启用跨域隔离后,工作器脚本也需要注意。添加了一些说明。
  • 2021 年 8 月 5 日:JS Self-Profiling API 曾被提及为需要跨域隔离的 API 之一,但为了反映最近的方向变化,我们已将其移除。
  • 2021 年 5 月 6 日:根据收到的反馈和报告的问题,我们决定调整在非跨域隔离网站中使用 SharedArrayBuffer 的时间表,以便在 Chrome M92 中进行限制。
  • 2021 年 4 月 16 日:添加了有关 COEP 无凭据模式和 COOP same-origin-allow-popups 作为跨域隔离的宽松条件的说明。
  • 2021 年 3 月 5 日:移除了对 SharedArrayBuffer、performance.measureUserAgentSpecificMemory() 和调试功能的限制,这些功能现已在 Chrome 89 中完全启用。添加了即将推出的功能 performance.now() 和 performance.timeOrigin,它们将具有更高的精确度。
  • 2021 年 2 月 19 日:添加了有关功能政策 allow="cross-origin-isolated" 和开发者工具调试功能的说明。
  • 2020 年 10 月 15 日:self.crossOriginIsolated 可从 Chrome 87 开始使用。 相应地,当 self.crossOriginIsolated 返回 true 时,document.domain 是不可变的。performance.measureUserAgentSpecificMemory() 的源试用即将结束,并且在 Chrome 89 中默认处于启用状态。Android Chrome 上的 Shared Array Buffer 将从 Chrome 88 开始提供。