使用 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
),则 opener 窗口和弹出式窗口共享相同的浏览上下文,因此它们可以通过 window.opener
API 等 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。
- 如果资源是使用 CORS 提供的,请在加载 HTML 标记中使用
- 对于 iframe,请遵循相同的原则并设置
Cross-Origin-Resource-Policy: cross-origin
(或根据上下文设置same-site
、same-origin
)。 - 使用
WebWorker
加载的脚本必须从同源提供,因此您无需 CORP 或 CORS 标头。 - 对于使用
COEP: require-corp
提供的文档或工作器,未加载 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
确认一切正常并且所有资源都可以成功加载后,为所有文档(包括通过 iframe 和工作器脚本嵌入的文档)将 Cross-Origin-Embedder-Policy-Report-Only
标头切换为具有相同值的 Cross-Origin-Embedder-Policy
标头。
使用 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 进行进一步改进,我们会不断更新这篇文章。