跨域 Web Worker?

18

我拥有 https://domain1.com (域名1) 和 https://domain2.com (域名2)。

域名2提供一个包含以下标题的JavaScript页面:

"Access-Control-Allow-Origin: *"

Domain1 运行一些 JavaScript 代码,调用:

new Worker("//domain2.com/script.js")

浏览器会抛出安全异常。

自从我开始撰写这个问题以来,我已经通过ajax脚本、blob的方式解决了这个问题,但是我在原始想法中错过了什么吗?


这里有两个重复的问题链接链接,但似乎都没有一个明确的答案。 - adeneo
根据MDN页面,使用ajax-data URL方法在所有浏览器中都不起作用。 - Pointy
2
根据我从W3C规范中了解到的,规则表明Worker脚本确实必须从拥有页面相同的域名中获取。我认为甚至不会检查CORS标头。 - Pointy
@Pointy Figures,因为网络选项卡甚至没有提示它正在获取页面进行检查。所以如果AJAX可以做到,为什么我们不能直接做呢? :/ - user1277170
我不知道它运作的原理。在ajax的情况下,那是一个较旧的标准。而且请注意,使用这种解决方法并不一定有效,因为一些浏览器会认为你构建的数据URL对于Web Worker来说并不属于“同源”。 - Pointy
这可能会帮助您解决此问题。https://dev59.com/C2Eh5IYBdhLWcg3w321G - Jiby Jose
4个回答

13

我也有同样的问题,希望这能帮到你 https://gist.github.com/jtyjty99999/a730a17258fca04bfca3

 function XHRWorker(url, ready, scope) {
      var oReq = new XMLHttpRequest();
      oReq.addEventListener('load', function() {
          var worker = new Worker(window.URL.createObjectURL(new Blob([this.responseText])));
          if (ready) {
              ready.call(scope, worker);
          }
      }, oReq);
      oReq.open("get", url, true);
      oReq.send();
  }

  function WorkerStart() {
      XHRWorker("http://static.xxx.com/js/worker.js", function(worker) {
          worker.postMessage("hello world");
          worker.onmessage = function(e) {
              console.log(e.data);
          }
      }, this);
  }

  WorkerStart();

请注意,这在IE11及以下版本上不起作用。那些浏览器会抛出一个“SecurityError”。 - Yuriy Nemtsov
哇,喜欢这个解决方案。特别是将 new BlobURL.createObjectURL 链接在一起。不知道这是可能的。 - Artur

8
注意:自Chrome v93+以来似乎无法正常工作,但John Hou的解决方案非常好用!(尽管现在使用fetch比使用XMLHttpRequest更容易检索代码)

这很有趣,但是在 worker 内部使用的 importScripts() 并没有相同的来源限制。因此我使用了这个简单的解决方法:

const workerUrl = 'https://domain2.com/script.js';
const workerBlob = new Blob([
    'importScripts(' + JSON.stringify(workerUrl) + ')',
], {type: 'application/javascript'});
const blobUrl = window.URL.createObjectURL(workerBlob);
const worker = new Worker(blobUrl);

有些比手动获取脚本要简单。

1
Chrome v107在这里,这个解决方案可行。 - Olli Niemitalo

5
注意:传递给 Worker 构造函数的 URI 必须遵守同源策略。目前,浏览器厂商对于哪些 URI 属于同源存在分歧;...
引用自 https://developer.mozilla.org/en-US/docs/Web/Guide/Performance/Using_web_workers HTML5 Worker 是一个相当新的概念,我不确定同源例外如何应用,但是通过 XmlHttpRequest,可以访问不同域上的资源,如果您控制运行该服务器的服务器。来自外部域的资源通过预检请求访问,这意味着首先向资源发送 OPTIONS 请求,如果响应具有适当的访问控制标头(Access-Control-Allow-MethodsAccess-Control-Allow-Origin 至少),则重复请求并接收响应中的资源。

1
这是正确的。然而,从Web Worker脚本获取过程的描述中,并不清楚用户代理是否应该检查标头。它只是强制从拥有页面来源获取URL,并设置“force same-origin flag”以确保重定向不能影响它。 - Pointy
我不确定... 引用的文档说“此外,它们可以使用XMLHttpRequest执行I/O操作...”。鉴于此,我认为底层传输仍然是标准的HTTP请求。 - marekful
哦,是的,我认为那是正确的。但是 规范 建议用户代理只从 "所有者源" 获取脚本。 - Pointy
这个规范在“所有者来源”方面存在歧义。显然,MDN文档指出,“作为Worker构造函数参数传递的URI必须遵守同源策略”,关于同源策略,它表示在某些条件下允许跨源访问:https://developer.mozilla.org/en-US/docs/Web/JavaScript/Same_origin_policy_for_JavaScript?redirectlocale=en-US&redirectslug=JavaScript%2FSame_origin_policy_for_JavaScript#Cross-origin_network_access - marekful
这是有道理的,因为跨域访问限制的目的是防止在资源所有者不希望其被访问时访问该资源。但如果您拥有多个来源,则可以在它们之间交叉访问资源。 - marekful
显示剩余3条评论

-3

你是否允许设置方法?

尝试将以下内容添加到您的头文件中:

Access-Control-Allow-Methods: POST, GET, OPTIONS

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接