繁体   English   中英

如何从服务器获取 JavaScript,跟踪下载进度,并且不在 Content-Security-Policy 中使用 `unsafe-eval`?

[英]How to fetch JavaScript from server, track download progress, and not use `unsafe-eval` in Content-Security-Policy?

我在服务器上有一个很重的 JavaScript 文件(> 3MB)。 我想快速加载页面并向用户显示加载进度条。 目前,我使用fetchWritableStream来下载数据并跟踪下载进度:

let resource = await fetch('heavy_file.js')
resource.clone().body.pipeTo(new WritableStream({
    write(t) { on_receive(t.length) }
}))

然后我使用函数来评估它。 这有几个问题。 我怎样才能:

  • 最好使用fetch加载脚本(我使用相同的方法加载 WASM 文件,我也想跟踪它们的下载进度,并且WebAssembly.compileStreaming API 需要使用fetch )。
  • 以一种适用于当今现代浏览器的方式跟踪下载进度。
  • 能够在不启用Content-Security-Policy 中的script-src 'unsafe-eval'情况下使用此解决方案吗?

附注。 当然,目前,在加载 WASM 文件时,我们需要在 Chrome 中使用script-src 'wasm-eval'直到bug被修复。

选项1

如果您可以计算您提前加载的脚本的哈希值(如果它不是动态生成的东西),那么一个简单的选项可以避免

在 Content-Security-Policy 中启用 script-src 'unsafe-eval'

将仅将该特定脚本的哈希添加到 CSP 标头中 - 这仍将确保您不会执行任何不受信任的代码,同时允许您手动加载和执行脚本。

MDN 在此处提供了更多实施此类 CSP 策略的示例。

至于加载本身,您有两条不同的路径:

选项 1.1

将哈希与 CSP3 策略unsafe-hashes ,这将允许您像当前一样继续使用Functioneval ,同时仍将代码限制为仅受信任。

例如,如果你有一个像

alert('Hello, world.');

那么您的 CSP 标头应包含

Content-Security-Policy: script-src 'unsafe-hashes' 'sha256-qznLcsROx4GACP2dm0UCKCzCG-HiZ1guq6ZZDob_Tng='

不幸的是,在撰写本文时,仅 Chromium 支持CSP 级别 3,或者至少此选项。

选项 1.2

您可以不使用Functioneval ,而是从 JavaScript 动态创建脚本标记,用您的响应内容填充其textContent并将其注入到 DOM 中:

let resource = await fetch('heavy_file.js')
resource.clone().body.pipeTo(new WritableStream({
    write(t) { on_receive(t.length) }
}));
resource.text().then(res => {
  let s = document.createElement('script');
  s.textContent = res;
  document.head.appendChild(s);
});

在这种情况下,您只需要将脚本的哈希值添加到 CSP 中,它就可以在所有浏览器上运行:

Content-Security-Policy: script-src 'sha256-qznLcsROx4GACP2dm0UCKCzCG-HiZ1guq6ZZDob_Tng='

选项 2

如果您确实希望支持动态生成的脚本,那么您唯一的选择可能是将进度跟踪代码移动到 Service Worker,然后使用Client.postMessage将进度传达给页面上的脚本。

这适用于从您的源提供的任何内容,但只有在安装了 Service Worker 之后 - 通常在后续页面加载时,如果您正在加载的大脚本是用户首先在您的页面上访问的页面的一部分,则可能无济于事网站。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM