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

使用 COOP 和 COEP 设置跨域隔离环境,并启用强大的功能,例如 SharedArrayBufferperformance.measureUserAgentSpecificMemory() 和更高精度的高分辨率计时器。

更新

  • 2022 年 6 月 21 日:启用跨域隔离后,Worker 脚本也需要注意。添加了一些说明。
  • 2021 年 8 月 5 日:JS 自我分析 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" 和 DevTools 上的调试功能的说明。
  • 2020 年 10 月 15 日self.crossOriginIsolated 从 Chrome 87 开始可用。反映这一点,当 self.crossOriginIsolated 返回 true 时,document.domain 是不可变的。performance.measureUserAgentSpecificMemory() 正在结束其源试用,并在 Chrome 89 中默认启用。Android Chrome 上的 Shared Array Buffer 将从 Chrome 88 开始提供。

一些 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 来确定网页是否处于跨域隔离状态。

本文介绍了如何使用这些新标头。在 后续文章 中,我将提供更多背景和上下文。

部署 COOP 和 COEP 以使您的网站跨域隔离

集成 COOP 和 COEP

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

通过在顶层文档上启用 COOP: same-origin,具有相同来源的窗口以及从该文档打开的窗口将具有单独的浏览上下文组,除非它们与相同的 COOP 设置处于相同的来源。因此,对打开的窗口强制实施隔离,并禁用两个窗口之间的相互通信。

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

Browsing Context Group

您可以从 DevTools 检查窗口打开器及其被打开者是否在不同的浏览上下文组中。

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> 等。

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

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

递归地将其应用于所有文档,包括顶层文档、iframe 和 worker 脚本。有关 Report-Only HTTP 标头的信息,请参阅 使用 Reporting API 观察问题

4. 启用 COEP

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

使用 self.crossOriginIsolated 确定隔离是否成功

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

使用 Chrome DevTools 调试问题

对于在屏幕上呈现的资源(例如图像),检测 COEP 问题非常容易,因为请求将被阻止,并且页面将指示缺少图像。但是,对于不一定具有视觉影响的资源(例如脚本或样式),COEP 问题可能会被忽略。对于这些资源,请使用 DevTools Network 面板。如果 COEP 存在问题,您应该在“状态”列中看到 (blocked:NotSameOriginAfterDefaultedToSameOriginByCoep)

COEP issues in the Status column of the Network panel.

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

Details of the COEP issue are shown in the Headers tab after clicking a network resource in the Network panel.

您还可以通过“Application”面板确定 iframe 和弹出窗口的状态。转到左侧的“Frames”部分,展开“top”以查看资源结构的细分。

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

Chrome DevTools iframe inspector

您还可以检查弹出窗口的状态,例如它是否是跨域隔离的。

Chrome DevTools popup window inspector

使用 Reporting API 观察问题

Reporting API 是另一种机制,您可以通过它检测各种问题。您可以配置 Reporting API 以指示用户的浏览器在 COEP 阻止资源加载或 COOP 隔离弹出窗口时发送报告。自版本 69 以来,Chrome 一直支持 Reporting API,用于各种用途,包括 COEP 和 COOP。

要了解如何配置 Reporting API 并设置服务器以接收报告,请访问 使用 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 的 DevTools 进行进一步改进时,我们将保持此帖子更新。

资源