使用 COOP 和 COEP 设置跨源隔离环境,并启用 SharedArrayBuffer
、performance.measureUserAgentSpecificMemory()
和高分辨率计时器等功能,从而提高精确度。
更新
- 2022 年 6 月 21 日:启用跨源隔离时,也需要注意 worker 脚本。添加了一些说明。
- 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 日:移除了对
SharedArrayBuffer
、performance.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 中默认处于启用状态。Android Chrome 上的共享数组缓冲区将从 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 标头加载。此步骤是第 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。
- 如果资源是使用 CORS 提供的,请在加载 HTML 标记中使用
- 对于 iframe,请遵循上述相同的原则,并设置
Cross-Origin-Resource-Policy: cross-origin
(或same-site
、same-origin
,具体取决于上下文)。 - 使用
WebWorker
加载的脚本必须从同源提供,因此您无需 CORP 或 CORS 标头。 - 对于使用
COEP: require-corp
提供的文档或 worker,未使用 CORS 加载的跨源子资源必须设置Cross-Origin-Resource-Policy: cross-origin
标头,以选择嵌入。例如,这适用于<script>
、importScripts
、<link>
、<video>
、<iframe>
等。
3. 使用 COEP 报告专用 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 问题可能会被忽略。如需了解这些信息,请使用 DevTools 的“Network”面板。如果 COEP 存在问题,您应该会在状态列中看到 (blocked:NotSameOriginAfterDefaultedToSameOriginByCoep)
。
然后,您可以点击相应条目查看更多详细信息。
您还可以通过应用面板确定 iframe 和弹出式窗口的状态。前往左侧的“帧”部分,然后展开“顶部”以查看资源结构的细分。
您可以检查 iframe 的状态,例如 SharedArrayBuffer
的可用性等。
您还可以检查弹出式窗口的状态,例如它是否是跨源隔离的。
使用 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 报告载荷示例如下所示:
[{
"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 相关的 DevTools 进行进一步改进,我们会不断更新这篇文章。