gma*_*man 5 html javascript security web-worker
我发现,至少在大多数在线代码编辑器(snippets/jsfiddle/codepen/glitch)上,我似乎无法从另一个域加载工作人员。我收到一个安全错误(或在 Firefox 静默失败中)
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);Run Code Online (Sandbox Code Playgroud)
在 Chrome 和 Safari 中我得到
SecurityError:无法构建“Worker”:无法从源“https://...”访问“ https://greggman.github.io/doodles/test/ping-worker.js ”处的脚本。
什么设置导致的?iframe 选项?页面的http标头?iframe 的 http 标头?来自脚本的 http 标头?)
我可以从工作人员和超时发送消息,但我想知道是否有一些不那么间接的方法来检查成功/失败
在任何情况下,我都可以通过自己获取脚本的文本来解决这个问题
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();Run Code Online (Sandbox Code Playgroud)
我询问了浏览器团队,并被告知手动获取并制作 blob url 是可以的,这导致了我的主要问题。
鉴于在什么情况下有解决方法没有解决方法?安全错误的重点是什么?浏览器供应商说我的解决方法很好,实际上我已经使用了 7-8 年的时间来将东西作为 blob url 启动。(html,脚本,但直到现在还不是工人)但是如果我的解决方法很好,那么错误的重点是什么?
问题#1:为什么我会收到该错误?
因为这就是规格所要求的。从获取经典工人
- 令 request 为一个新请求,其 url 为url,客户端为fetch client settings object,目的地为 destination ,模式为
"same-origin",凭据模式为"same-origin",解析器元数据为"not parser-inserted",并且设置了其 use-URL-credentials 标志。
因此,请求的模式将设置为"same-origin",因此,它将失败:
(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' ); }
})();Run Code Online (Sandbox Code Playgroud)
问题#2:有没有办法在 Firefox 中检测到这个问题?
当然,您只需监听error将在您的 Worker 对象上分派的事件:
const url = "https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"
const worker = new Worker( url );
worker.onerror = console.error;Run Code Online (Sandbox Code Playgroud)
问题#3:鉴于解决方法很简单,此安全错误的意义何在?
因为你的 Worker 的内部起源取决于此。参考
将工作人员全局范围的url设置为响应的 url。
因此,如果他们允许此处的“no-cors”请求,您将能够从您的 Worker 获取该服务器上的资源,从而绕过跨源限制。
通过先获取它,然后创建同源(blob:URI)或不透明源(data:URI)上下文,就不存在这样的问题。
请注意,只有对 Worker 脚本的初始请求才会受到此限制,因此解决初始问题的另一种方法是使用“同源”importScripts 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 ] ) );
}Run Code Online (Sandbox Code Playgroud)
<script id="source" type="worker">
importScripts("https://greggman.github.io/doodles/test/ping-worker.js");
</script>Run Code Online (Sandbox Code Playgroud)