使用 COOP 和 COEP 将网站设置为“跨源隔离”

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

更新

  • 2022 年 6 月 21 日:启用跨域隔离后,还需要注意工作器脚本。添加了一些说明。
  • 2021 年 8 月 5 日:JS Self-Profiling API 已被提及为需要跨域隔离的 API 之一,但根据方向的近期更改,已被移除。
  • 2021 年 5 月 6 日:根据反馈和报告的问题,我们决定调整在 Chrome M92 中限制在非跨源隔离网站中使用 SharedArrayBuffer 的时间表。
  • 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 日:Chrome 87 及更高版本支持 self.crossOriginIsolated。 因此,当 self.crossOriginIsolated 返回 true 时,document.domain 不可变。performance.measureUserAgentSpecificMemory() 即将结束其源试用,在 Chrome 89 中默认处于启用状态。Chrome 88 及更高版本将支持 Android Chrome 上的 Shared Array Buffer。

某些 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),那么该窗口和弹出式窗口会共享相同的浏览上下文,因此可以通过 window.opener 等 DOM API 相互访问。

浏览上下文组

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

2. 确保资源已启用 CORP 或 CORS

请确保网页中的所有资源均已加载 CORP 或 CORS HTTP 标头。要进行第 4 步,启用 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 提供的文档或工作器,非 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 和工作器脚本。如需了解“仅限报告”HTTP 标头,请参阅使用 Reporting API 观察问题

4. 启用 COEP

确认一切正常且所有资源都可以成功加载后,将 Cross-Origin-Embedder-Policy-Report-Only 标头切换到具有相同值的 Cross-Origin-Embedder-Policy 标头,从而为所有文档(包括通过 iframe 和工作器脚本嵌入的文档)添加相同的值。

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

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

使用 Chrome 开发者工具调试问题

对于在屏幕上呈现的资源(如图片),您可以很容易地检测到 COEP 问题,因为请求将被禁止,并且网页会指示图片缺失。但是,对于不一定具有视觉影响的资源(例如脚本或样式),COEP 问题可能会被忽略。对于这种情况,请使用开发者工具的 Network 面板。如果 COEP 存在问题,您应该会在状态列中看到 (blocked:NotSameOriginAfterDefaultedToSameOriginByCoep)

“Network”面板的“状态”列中显示的 COEP 问题。

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

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

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

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

Chrome 开发者工具 iframe 检查器

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

Chrome DevTools 弹出式窗口检查器

使用 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"
}]

当不同的浏览上下文组尝试相互访问时(仅在“仅限报告”模式下),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 对开发者工具进行了进一步改进。

资源