5

因此,SharedArrayBuffer 最近仅限于跨域隔离页面作为安全修复。

我们有一个依赖于 SharedArrayBuffer 的工具,我通过将它移动到一个去掉所有其他站点 UI 的准系统页面并发送以下标头来重新设计它以再次工作:

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

尝试将它加载到成熟网站的 iframe 中会给我带来控制台错误SharedArrayBuffer will require cross-origin isolation as of M92,然后是ReferenceError: SharedArrayBuffer is not defined- 与我在跨域隔离最小页面本身上的工具之前得到的相同。

我试图在其中包含 iframe 的页面不是跨域隔离的。如果不是不可能,那将是非常困难的。我根本不需要从父页面与 iframe 交谈,这只是一种方便/风格的东西。目前的生产解决方案只是将用户链接到新窗口中的最小跨源工具页面,但这很尴尬。

我希望有一些 iframe沙盒属性的组合或者可以使这项工作正常进行的东西?我为此奋斗了几个小时。

据我所知,这可能不可行。

4

2 回答 2

0

尝试在 iframe 的属性中添加allow-scripts和标记:allow-same-originsandbox

<iframe src="…&quot; sandbox="allow-scripts allow-same-origin"></iframe>
                         ^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^

以下是有关该主题的一些相关资源:


首先尝试上述方法,如果它对您遇到的问题没有帮助SharedArrayBuffer,那么事情会更复杂一些。

正确的跨域需要来自子资源的显式标头(<iframe>必须发送标头),当子资源是第三方且失控时,这是一个大问题。为了缓解这个问题,有一个建议Cross-Origin-Embedder-Policy: credentialles

但是,有一个问题:它不会改变<iframe>工作方式(真可惜,这正是我们所需要的!)。有一个关于匿名 iframe 的讨论,可以解决这个问题,但还没有解决,所以我不会在这里屏住呼吸。

因此,剩下的唯一选择是延迟 Chrome 行为的这种更改(可以在 Chrome 103 之前完成):

  1. 为您的来源请求令牌
  2. 将令牌添加到您的页面。有两种方法可以做到这一点:
    • <meta>在每个页面的头部添加一个标签。例如,这可能看起来像:<meta http-equiv="origin-trial" content="TOKEN_GOES_HERE">
    • 如果您可以配置您的服务器,您还可以使用Origin-TrialHTTP 标头添加令牌。生成的响应标头应类似于:Origin-Trial: TOKEN_GOES_HERE
于 2021-12-15T14:57:20.847 回答
-1

我不确定此选项是否适合您的情况,但也许它可以帮助您找到完整的解决方案。这篇博文描述了通过在 ServiceWorker 中修改标头来启用 SharedArrayBuffer 它按以下顺序工作:

  1. 第一次加载页面时,会注册一个 Service Worker
  2. 页面已重新加载
  3. SharedArrayBuffer 变得可用,因为 ServiceWorker 控制所有请求的所有 CORS 标头

Service Worker 通过添加 CORS/COEP 标头来修改所有请求(示例取自上述博文):

self.addEventListener("install", function() {
  self.skipWaiting();
});

self.addEventListener("activate", (event) => {
  event.waitUntil(self.clients.claim());
});

self.addEventListener("fetch", function(event) {
  if (event.request.cache === "only-if-cached" && event.request.mode !== "same-origin") {
    return;
  }

  event.respondWith(
    fetch(event.request)
    .then(function(response) {
      // It seems like we only need to set the headers for index.html
      // If you want to be on the safe side, comment this out
      // if (!response.url.includes("index.html")) return response;

      const newHeaders = new Headers(response.headers);
      newHeaders.set("Cross-Origin-Embedder-Policy", "require-corp");
      newHeaders.set("Cross-Origin-Opener-Policy", "same-origin");

      const moddedResponse = new Response(response.body, {
        status: response.status,
        statusText: response.statusText,
        headers: newHeaders,
      });

      return moddedResponse;
    })
    .catch(function(e) {
      console.error(e);
    })
  );
});

于 2021-12-13T06:23:53.717 回答