【问题标题】:SharedArrayBuffer in an IframeIframe 中的 SharedArrayBuffer
【发布时间】:2021-12-07 15:08:25
【问题描述】:

所以 SharedArrayBuffer 最近被limited to Cross-origin isolated pages 作为安全修复程序。

我们有一个依赖于 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 sandbox attributes 的组合或者可以使它工作的东西?我为此奋斗了几个小时。

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

【问题讨论】:

    标签: javascript html iframe sharedarraybuffer


    【解决方案1】:

    尝试在 iframe 的 sandbox 属性中添加 allow-scriptsallow-same-origin 标记:

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

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


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

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

    但是,有一个问题:it doesn't change how &lt;iframe&gt; works(真可惜,这正是我们所需要的!)。有a discussion about anonymous iframes,可以解决这个问题,但是还没有解决,所以我不会在这里屏住呼吸。

    所以,剩下的唯一选择是delay this change in Chrome behavior(可以在 Chrome 103 之前完成):

    1. Request a token 代表您的出身。
    2. 将令牌添加到您的页面。有两种方法可以做到这一点:
      • 在每个页面的头部添加一个&lt;meta&gt; 标签。例如,这可能类似于:&lt;meta http-equiv="origin-trial" content="TOKEN_GOES_HERE"&gt;
      • 如果您可以配置您的服务器,您还可以使用Origin-Trial HTTP 标头添加令牌。生成的响应标头应类似于:Origin-Trial: TOKEN_GOES_HERE

    【讨论】:

      【解决方案2】:

      我不确定此选项是否适合您的情况,但也许它可以帮助您找到完整的解决方案。 blogpost 描述了通过 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);
          })
        );
      });

      【讨论】:

      • 这并不能解决我的问题,这只是减轻了设置标题的需要,这不是我遇到的问题。我完全能够设置标头服务器端。我已经让工具本身在一个设置了标题的页面上工作,没有别的。问题是标头破坏了正常站点上的所有内容,即从 CDN 加载 JS。重新设计整个站点并维护此工具的更改是一个选项。这就是我想在 iframe 中加载最小工作工具的原因 - 我感觉这是不可能的,但我不确定为什么会存在这样的限制。
      • 那么,据我所知,目前还没有办法在 iframe 中使用共享数组缓冲区。这已经在这里讨论过stackoverflow.com/questions/69322834/…
      猜你喜欢
      • 2017-11-28
      • 1970-01-01
      • 1970-01-01
      • 2021-10-07
      • 1970-01-01
      • 2021-06-23
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多