所以SharedArrayBuffer最近被限制为跨源隔离页面作为安全修复。
我们有一个依赖于SharedArrayBuffer的工具,我重新设计了它,使再次工作通过将其移动到一个除去所有其他网站UI的barebones页面,并发送以下标题:
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沙盒属性的组合或一些东西,将使这个工作?我为此争论了几个小时。
据我所知,这可能不可行。
尝试在iframe的sandbox
属性中添加allow-scripts
和allow-same-origin
标记:
<iframe src="…" sandbox="allow-scripts allow-same-origin"></iframe>
^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^
以下是关于这个主题的一些相关资源:
- 沙箱,IFrame和allow-same-origin (StackOverflow问题)
- 通过sandbox属性保护iframe
<iframe>
:内联框架元素(MDN文档),-不要错过注意
先试试上面的,如果它对你的SharedArrayBuffer
问题没有帮助,那么事情就有点复杂了。
正确的跨源需要子资源的显式头(<iframe>
必须发送头),当子资源是第三方且失控时,这是一个大问题。为了缓解这个问题,有一个提案Cross-Origin-Embedder-Policy: credentialles
。
然而,有一个问题:它不会改变<iframe>
的工作方式(遗憾的是,这正是需要的!)。有一个关于匿名iframe的讨论,这将解决这个问题,但它还没有解决,所以我不会屏住呼吸在这里。
所以,剩下的唯一选择是延迟Chrome行为的变化(可以在Chrome 103之前完成):
- 请求原点令牌
- 将令牌添加到页面中。有两种方法:
- 在每个页面的头部添加一个
<meta>
标签。例如,这可能看起来像:<meta http-equiv="origin-trial" content="TOKEN_GOES_HERE">
- 如果你可以配置你的服务器,你也可以使用
Origin-Trial
HTTP头添加令牌。结果的响应头应该看起来像:Origin-Trial: TOKEN_GOES_HERE
我不确定这个选项是否适合您的情况,但也许它可以帮助您找到一个完整的解决方案。这篇博文描述了在ServiceWorker中通过头部修改来启用SharedArrayBuffer。它的工作顺序如下:
- 当页面第一次加载时,一个Service worker被注册
- 页面重新加载
- SharedArrayBuffer变得可用,因为ServiceWorker控制所有请求的所有CORS头
Service Worker通过添加CORS/COEP头来修改所有请求(该示例取自上述blogpost):
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);
})
);
});