为什么跨源工作人员被阻止,变通办法为何可以解决? [英] Why are cross origin workers blocked and why is the workaround ok?

查看:90
本文介绍了为什么跨源工作人员被阻止,变通办法为何可以解决?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

最近,我在一个图书馆上工作,该图书馆支持使用工人进行一些繁重的工作.

Recently I worked on a library that supports using workers for some heavy lifting.

我发现,至少在大多数在线代码编辑器(代码段/jsfiddle/codepen/glitch)上,我似乎无法从另一个域中加载工作程序.我收到一个安全错误(或在firefox静默失败中)

I found out that, at least on most online code editors (snippets/jsfiddle/codepen/glitch) I can't seem to load a worker from another domain. I get a security error (or in firefox silent failure)

function startWorker(url) {
  try {
    const worker = new Worker(url);
    console.log('started worker');
    worker.onmessage = e => log('black', e.data);
    worker.postMessage('Hi from page');
  } catch (e) {
    console.error('could not start worker:', e);
  }
}

const workerURL = 'https://greggman.github.io/doodles/test/ping-worker.js';
startWorker(workerURL);

在Chrome和Safari中,我得到了

In Chrome and Safari I get

SecurityError:无法构造'Worker':位于' https:/不能从来源'https://...'访问/greggman.github.io/doodles/test/ping-worker.js .

问题1:为什么会出现该错误?

什么设置导致它? iframe选项?页面的http标头? iframe的http标头?脚本中的http标头?)

Question #1: Why do I get that error?

What setting causes it? iframe options? http headers for the page? http headers for the iframe? http headers from the script?)

我可以发送来自工作人员和超时的消息,但是我想知道是否存在一些间接的成功/失败检查方法

I can send a message from the worker and timeout but I'm wondering if there is some less indirect way of checking for success/failure

无论如何,我都可以自己获取脚本文本来解决此问题

In any case I can work around this issue by fetching the text of the script myself

function startWorker(url) {
  try {
    const worker = new Worker(url);
    console.log('started worker');
    worker.onmessage = e => console.log(e.data);
    worker.postMessage('Hi from page');
  } catch (e) {
    console.error('could not start worker:', e);
  }
}

async function main() {
  const workerURL = 'https://greggman.github.io/doodles/test/ping-worker.js';

  const res = await fetch(workerURL);
  const text = await res.text();
  const blob = new Blob([text], {type: 'application/javascript'});
  const url = URL.createObjectURL(blob);

  startWorker(url);
}
main();

我问过浏览器团队,并被告知手动进行提取,然后创建一个Blob网址是可以的,这导致了我的主要问题.

I asked the browser teams and was told fetching manually and making a blob url is okay which leads to my main question.

鉴于有什么解决方法,在什么情况下没有解决方法?安全错误的意义何在?浏览器供应商说我的解决方法很好,实际上我已经将功能启动功能作为blob url使用了7至8年. (html,脚本,但现在为止不支持工作器),但是如果我的解决方法没问题,那么错误的意义何在?

Given there is a workaround in what situation is there no workaround? What is the point of the Security Error? The browser vendors say my workaround is fine and I've actually be using the ability launch things as blob urls for 7-8 years. (html, scripts, but not workers until now) but if my workaround is fine then what is the point of the error?

推荐答案

问题1:为什么会出现该错误?

因为这就是规格要求.从 获取一名经典工人

Because that's what the specs ask. From fetch a classic worker

  1. 让请求成为一个新请求,其URL为 url ,客户​​端为获取客户端设置对象,目标为目的地,方式为,凭据模式为"same-origin",解析器元数据为"not parser-inserted",并且其use-URL-credentials标志已设置.
  1. Let request be a new request whose url is url, client is fetch client settings object, destination is destination, mode is "same-origin", credentials mode is "same-origin", parser metadata is "not parser-inserted", and whose use-URL-credentials flag is set.

因此,请求的模式将设置为"same-origin",因此将失败:

So the request will have its mode set to "same-origin", and because of that, it will fail:

(async ()=>{
const url = "https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js";
try {
  console.log( 'default ("no-cors")' )
await fetch( url )
  console.log( 'success' );
}
catch(e) { console.log( 'failed' ); }

try {
  console.log( 'like workers ("same-origin")' )
await fetch( url, { mode: "same-origin" } )
  console.log( 'success' );
}
catch(e) { console.log( 'failed' ); }

})();

问题2:有没有办法在Firefox中检测到此问题?

当然,您只需要侦听将在Worker对象上调度的error事件:

Sure, you just have to listen for the error event that will be dispatched on your Worker object:

const url = "https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"
const worker = new Worker( url );
worker.onerror = console.error;

问题3:鉴于解决方法很简单,此安全错误的意义何在?

因为您的工人的内部血统取决于此. 参考

Because the internal origin of your Worker depends on this. ref

将工作程序全局范围的 url 设置为响应的URL.

Set worker global scope's url to response's url.

因此,如果他们允许无芯",则在这里提出要求,您就可以绕过跨域限制,从Worker中获取该服务器上的资源.

So if they were to allow a "no-cors" request here, you would be able to fetch resources on that server from your Worker, bypassing the cross-origin restrictions.

首先获取它,然后创建一个 same-origin (blob:URI)或一个 opaque origin (data:URI)上下文,就没有这样的问题

By fetching it first, and then creating a same-origin (blob:URI) or an opaque origin (data:URI) context, there is no such problem.

请注意,只有对Worker脚本的初始请求受此限制,因此解决初始问题的另一种方法是使用 Worker内部进行的:

Note that only the initial request to the Worker's script is subject to this limitation, so an other way to work around your initial issue is to use the importScripts method from inside a "same-origin" Worker:

const worker = new Worker( getURL() );
worker.onmessage = (evt) => console.log(evt.data);


function getURL() {
  const txt = document.getElementById( 'source' ).textContent;
  return URL.createObjectURL( new Blob( [ txt ] ) );
}

<script id="source" type="worker">
  importScripts("https://greggman.github.io/doodles/test/ping-worker.js");
</script>

这篇关于为什么跨源工作人员被阻止,变通办法为何可以解决?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆