fetch 的 integrity 属性仅校验当前响应体本身,不校验脚本内部 import 或动态请求的子资源;需手动结合 fetch + 哈希比对、script 标签注入或构建时生成 sri 清单实现全流程保护。

Fetch 的 integrity 属性本身不直接用于校验脚本的“子资源”(比如该脚本内部 import 的模块、动态 import() 加载的代码,或通过 fetch / XMLHttpRequest 请求的其他资源),它只校验当前 fetch 请求**响应体本身**的完整性。也就是说:当你用 fetch(url, { integrity: "sha256-..." }) 请求一个 JS 文件时,浏览器会验证这个 JS 文件的内容是否匹配指定的哈希值——仅此而已。
integrity 属性的作用范围有限
Integrity 校验是 Fetch 规范中定义的“subresource integrity”(SRI)机制的一部分,但目前只在以下场景被浏览器强制执行:
-
<script src="..." integrity="..."></script>(HTML 解析阶段) <link rel="stylesheet" href="..." integrity="...">-
fetch(url, { integrity: "..." })(仅对响应 body 做哈希比对,且仅当响应 MIME 类型属于可信任类型,如text/javascript、application/javascript等)
它不会递归检查脚本运行时触发的任何后续网络请求(例如 import('./chunk.js')、fetch('/api/data.json')、document.createElement('script').src = '...'),这些行为完全脱离 SRI 控制。
如何让动态加载的脚本也受完整性保护
若你希望某个由主脚本动态引入的子脚本(如 ES 模块、按需 chunk)也具备完整性校验,必须手动干预,不能依赖自动机制。常用做法有:
-
用
import()+ 预置哈希 + 自定义加载器:先 fetch 脚本并校验哈希,再用Blob+URL.createObjectURL创建地址,最后import()它 -
改用
<script></script>标签注入:创建 script 元素,设置src和integrity属性,再 append 到 DOM —— 这样浏览器会按标准 SRI 流程校验 -
服务端配合做签名/哈希透出:API 返回子资源 URL 时,同时返回其预期哈希(如
{"url": "/js/chunk-abc.js", "integrity": "sha384-..."}),前端 fetch 后手动比对
fetch 中使用 integrity 的正确写法
要启用 fetch 的 integrity 校验,需满足两个前提:
- 请求的
mode必须是"cors"或"no-cors"(但"no-cors"下 integrity 会被忽略,所以实际应设为"cors") - 响应头需包含
crossorigin(即服务端返回Access-Control-Allow-Origin,且资源支持 CORS)
示例:
fetch('/js/main.js', {integrity: 'sha256-abc123...',
method: 'GET',
mode: 'cors'
})
.then(r => r.text())
.catch(err => console.error('校验失败或网络错误:', err));
注意:如果响应 body 哈希不匹配,Promise 会以 TypeError 拒绝,且无法捕获具体是哪一步失败(网络 or 哈希)。
替代方案:用 Subresource Integrity + 构建工具保障全流程
真正可靠的子资源完整性,应从构建阶段开始控制:
- 用 Webpack/Vite/Rollup 在打包时生成每个 chunk 的 SRI 哈希,并写入 HTML 或 manifest.json
- 服务端渲染(SSR)时,根据 manifest 注入带
integrity的<script></script>标签 - 对动态 import,可封装一个安全的
safeImport(path)函数,内部查 manifest 获取哈希,再 fetch + 校验 + import
这样就把完整性校验从“运行时不可控”变为“构建时确定、加载时可验证”的闭环。










