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

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

更新

  • 2022 年 6 月 21 日:启用跨源隔离时,还需要注意 Worker 脚本。添加了一些说明。
  • 2021 年 8 月 5 日:JS 自分析 API 曾被提及为需要跨源隔离的 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 上的 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)相互访问。

浏览上下文组

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

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 脚本。如需了解有关“仅报告”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 开发者工具调试问题

对于在屏幕上呈现的资源(例如图片),检测 COEP 问题相当容易,因为请求会被阻止,并且网页会指示缺少图片。不过,对于不一定具有视觉影响的资源(例如脚本或样式),COEP 问题可能不会引起注意。对于这些请求,请使用开发者工具的“网络”面板。如果 COEP 存在问题,您应该会在状态列中看到 (blocked:NotSameOriginAfterDefaultedToSameOriginByCoep)

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

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

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

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

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

Chrome 开发者工具 iframe 检查器

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

Chrome 开发者工具弹出式窗口检查器

使用 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 对开发者工具进行进一步改进,我们会不断更新此博文。

资源