首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >为什么跨来源的工人被封锁,为什么解决办法是好的?

为什么跨来源的工人被封锁,为什么解决办法是好的?
EN

Stack Overflow用户
提问于 2019-09-25 12:14:53
回答 1查看 1.7K关注 0票数 6

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

我发现,至少在大多数在线代码编辑器(片段/jsfiddle/codepen/glitch)上,我似乎无法从另一个域加载一个工作人员。我得到了一个安全错误(或者在firefox无声故障中)

代码语言:javascript
运行
复制
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里

SecurityError:未能构造'Worker':在'https://greggman.github.io/doodles/test/ping-worker.js‘处的脚本无法从原始的'https://...'’访问。

问题1:为什么我会犯这个错误?

是什么环境造成的?如果有选择的话?网页的http标题?iframe的http标头?来自脚本的http头?)

问题2:在firefox中有检测此问题的方法吗?

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

在任何情况下,我都可以通过自己获取脚本文本来解决这个问题。

代码语言:javascript
运行
复制
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 url是可以的,这就引出了我的主要问题

问题3:这个安全错误的意义是什么?

如果有一个解决办法,在什么情况下没有解决办法?安全错误的意义是什么?浏览器供应商说,我的解决办法很好,而且我已经使用了7-8年的blob启动功能。(html,脚本,但直到现在还没有工人)但是如果我的解决方案很好,那么错误的意义是什么?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2020-02-01 10:12:00

问题1:为什么我会犯这个错误?

因为这就是规范要求的。来自https://html.spec.whatwg.org/multipage/webappapis.html#fetch-a-classic-worker-script

  1. 将请求设为新请求,其url为url,客户端为获取客户端设置对象,目标为目标,模式为"same-origin",凭据模式为"same-origin",解析器元数据为"not parser-inserted",并设置了使用URL-凭据标志。

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

代码语言:javascript
运行
复制
(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事件:

代码语言:javascript
运行
复制
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:这个安全错误的意义是什么?

因为你的工人的内部来源取决于此。参考

将worker全局范围的url设置为响应的url。

因此,如果他们在这里允许一个“no”请求,您就可以绕过跨源限制,从您的工作人员那里获取服务器上的资源。

首先获取它,然后创建一个相同的原点(blob:URI)或一个不透明的原点(data:URI)上下文,就没有这样的问题了。

请注意,只有对工人脚本的初始请求受此限制,因此解决初始问题的另一种方法是在“相同来源”的工作人员内部使用importScripts方法:

代码语言:javascript
运行
复制
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 ] ) );
}
代码语言:javascript
运行
复制
<script id="source" type="worker">
  importScripts("https://greggman.github.io/doodles/test/ping-worker.js");
</script>

票数 4
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/58098143

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档