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

使用 COOP 和 COEP 设置跨域隔离环境,并启用 强大的功能,例如 SharedArrayBufferperformance.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-sitesame-origin,具体取决于上下文)。
  • 使用 WebWorker 加载的脚本必须从同一来源提供,因此您不需要 CORP 或 CORS 标头。
  • 对于使用 COEP: require-corp 提供的文档或 worker,在没有 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 和 worker 脚本。如需了解 Report-Only HTTP 标头,请参阅 使用 Reporting API 观察问题

4. 启用 COEP

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

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

确定隔离是否成功

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

调试问题

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

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

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

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

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

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

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

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

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

Chrome 开发者工具 iframe 检查器。

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

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

使用 Reporting API 观察问题

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

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

COEP 报告示例

阻止跨域资源时的 COEP 报告 载荷示例如下所示:

[{
  "age": 25101,
  "body": {
    "blocked-url": "https://third-party-test.glitch.me/check.svg?",
    "blockedURL": "https://third-party-test.glitch.me/check.svg?",
    "destination": "image",
    "disposition": "enforce",
    "type": "corp"
  },
  "type": "coep",
  "url": "https://cross-origin-isolation.glitch.me/?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.glitch.me/popup?report-only&coop=same-origin&",
    "type": "navigation-from-response"
  },
  "type": "coop",
  "url": "https://cross-origin-isolation.glitch.me/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"
}]

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

[{
  "age": 51785,
  "body": {
    "columnNumber": 18,
    "disposition": "reporting",
    "effectivePolicy": "same-origin",
    "lineNumber": 83,
    "property": "postMessage",
    "sourceFile": "https://cross-origin-isolation.glitch.me/popup.js",
    "type": "access-from-coop-page-to-openee"
  },
  "type": "coop",
  "url": "https://cross-origin-isolation.glitch.me/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.glitch.me/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 以确定网页是否处于跨域隔离状态。

我们会随着此跨域隔离状态提供新功能,并进一步改进与 COOP 和 COEP 相关的开发者工具,不断更新这篇文章

资源

文档更新

  • 2022 年 6 月 21 日:启用跨域隔离 时,worker 脚本也需要注意。添加了一些说明。
  • 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 日:移除了对 SharedArrayBufferperformance.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 上的共享数组缓冲区将从 Chrome 88 开始提供。