Android Chrome 88 和桌面版 Chrome 92 中的 SharedArrayBuffer 更新

可以说,SharedArrayBuffer 在 Web 上发布时遇到了一些问题,但现在一切都已恢复正常。以下是您需要知晓的相关信息:

简要说明

  • Firefox 79 及更高版本目前支持 SharedArrayBuffer,Android 版 Chrome 88 也将支持 SharedArrayBuffer。不过,它仅适用于跨源隔离的网页。
  • SharedArrayBuffer 目前在桌面版 Chrome 中可用,但从 Chrome 92 开始,将仅限于跨源隔离的网页。如果您认为自己无法及时进行此更改,可以注册原始来源试用版,以便在至少 Chrome 113 之前保留当前行为。
  • 如果您打算启用跨源隔离以继续使用 SharedArrayBuffer,请评估这对您网站上的其他跨源元素(例如广告展示位置)的影响。检查您的任何第三方资源是否使用了 SharedArrayBuffer,以了解影响和相关指南。

跨源隔离概览

您可以通过使用以下标头提供网页来使网页实现跨源隔离

Cross-Origin-Embedder-Policy: require-corp
Cross-Origin-Opener-Policy: same-origin

执行此操作后,您的网页将无法加载跨源内容,除非资源通过 Cross-Origin-Resource-Policy 标头或 CORS 标头(Access-Control-Allow-* 等)明确允许。

此外,还有一个 Reporting API,可让您收集因 Cross-Origin-Embedder-PolicyCross-Origin-Opener-Policy 而失败的请求的数据。

如果您认为自己无法在 Chrome 92 发布之前及时进行这些更改,可以注册参与源代码试用,以便在至少 Chrome 113 之前保留当前的桌面版 Chrome 行为。

如需有关跨源隔离的更多指南和信息,请参阅本页底部的阅读更多部分。

我们为何会陷于如此境地?

SharedArrayBuffer 在 Chrome 60 中推出(对于那些以日期而非 Chrome 版本来衡量时间的用户,该版本对应的是 2017 年 7 月),一切都很顺利。为期 6 个月。

2018 年 1 月,一些热门 CPU 中存在的漏洞被曝光。如需了解完整详情,请参阅公告,但这在本质上意味着代码可以使用高分辨率计时器读取不应访问的内存。

这对我们浏览器供应商来说是一个问题,因为我们希望允许网站以 JavaScript 和 WASM 的形式执行代码,但要严格控制此代码可以访问的内存。如果您访问我的网站,我应该无法读取您同时打开的网上银行网站中的任何内容。事实上,我甚至不知道您是否打开了网银网站。这些是 Web 安全的基础知识。

为缓解此问题,我们降低了 performance.now() 等高分辨率计时器的分辨率。不过,您可以通过在工作器的紧密循环中修改内存,并在另一个线程中读回内存,使用 SharedArrayBuffer 创建高分辨率计时器。若要有效缓解此问题,就必须严重影响有意图的代码,因此 SharedArrayBuffer 已被完全停用。

常见的缓解措施是确保网页的系统进程不包含来自其他位置的敏感数据。Chrome 从一开始就投入了大量精力来打造多进程架构(还记得漫画吗?),但在某些情况下,来自多个网站的数据仍可能会最终出现在同一进程中:

<iframe src="https://your-bank.example/balance.json"></iframe>
<script src="https://your-bank.example/balance.json"></script>
<link rel="stylesheet" href="https://your-bank.example/balance.json" />
<img src="https://your-bank.example/balance.json" />
<video src="https://your-bank.example/balance.json"></video>
<!-- …and more… -->

这些 API 具有“旧版”行为,允许在无需从其他来源选择启用的情况下使用其他来源的内容。这些请求是使用其他来源的 Cookie 发出的,因此是完整的“已登录”请求。现在,新 API 要求其他来源使用 CORS 选择启用。

我们通过阻止内容在看起来“不正确”时进入网页进程来规避这些旧版 API,并将其称为跨源读取屏蔽。因此,在上述情况下,我们不允许 JSON 进入该流程,因为它不是任何这些 API 的有效格式。也就是说,iframe 除外。对于 iframe,我们会将内容放入其他进程中。

在采取这些缓解措施后,我们在 Chrome 68(2018 年 7 月)中重新引入了 SharedArrayBuffer,但仅限桌面设备。由于额外的流程要求,我们无法在移动设备上执行相同的操作。他们还指出,Chrome 的解决方案并不完善,因为我们只会屏蔽“不正确”的数据格式,而可猜测网址中的有效 CSS/JS/图片有可能(虽然不常见)包含私密数据。

Web 标准团队共同制定了更完整的跨浏览器解决方案。解决方案是让网页能够以某种方式声明“我在此放弃在未经用户选择的情况下将其他来源的内容引入此流程的权限”。此声明是通过随网页一起提供的 COOP 和 COEP 标头完成的。浏览器会强制执行此操作,作为交换,网页可以访问 SharedArrayBuffer 和其他具有类似权限的 API。其他来源可以通过 Cross-Origin-Resource-PolicyCORS 选择启用内容嵌入。

Firefox 是第一个在 79 版(2020 年 7 月)中发布带有此限制的 SharedArrayBuffer 的浏览器。

然后,在 2021 年 1 月,我撰写了这篇文章,而您正在阅读它。你好。

这就是目前的情况。Chrome 88 为 Android 上的跨源隔离页面重新引入了 SharedArrayBuffer,Chrome 92 则在桌面设备上引入了相同的要求,以实现一致性并实现完全的跨源隔离。

推迟桌面版 Chrome 更改

这项临时性例外情况采用“源试用”形式,旨在为用户提供更多时间来实现跨源隔离的网页。它可启用 SharedArrayBuffer,而无需对页面进行跨源隔离。此例外情况将在 Chrome 113 中失效,并且仅适用于桌面版 Chrome。

  1. 为您的来源请求令牌
  2. 将令牌添加到您的网页。您可以通过以下两种方式执行此操作:
    • 在每个网页的标头中添加 origin-trial <meta> 标记。例如,可能如下所示:
      <meta http-equiv="origin-trial" content="TOKEN_GOES_HERE">
    • 如果您能配置服务器,则还可以使用 Origin-Trial HTTP 标头添加令牌。生成的响应标头应如下所示:
      Origin-Trial: TOKEN_GOES_HERE

深入阅读

横幅照片由 Unsplash 用户 Daniel Gregoire 拍摄