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

可以说,SharedArrayBuffer 在 Web 上推出时遇到了一些问题,但现在情况正在好转。以下是您需要知晓的相关信息:

简而言之

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

跨源隔离概览

您可以通过提供带有以下 HTTP 标头的网页,使网页实现跨源隔离

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(2017 年 7 月,对于那些以日期而非 Chrome 版本来衡量时间的人来说)中推出,一切都很顺利。 期限为 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,JSON 都不是有效格式。也就是说,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 将 SharedArrayBuffer 带回了 Android,用于跨源隔离的网页;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

深入阅读

横幅照片由 Daniel GregoireUnsplash 上提供