SRI校验必须同时设置integrity和crossorigin属性才生效;仅script和link[rel="stylesheet"]支持,哈希须基于线上URL实际响应体(解压后明文)用sha384-base64生成。

integrity属性必须和crossorigin="anonymous"一起写
只写 integrity 属性,浏览器压根不校验——它连资源响应体都读不到。SRI(子资源完整性)校验强制走 CORS 流程,而 crossorigin 是触发该流程的开关。漏掉、写错(比如 crossorigin="true")、或写成空字符串 crossorigin=""(Firefox 会拒绝解析),都会导致校验静默跳过。
公开 CDN(如 jsDelivr、unpkg、cdnjs)一律用 crossorigin="anonymous";只有极少数自有后端需带 Cookie 加载 JS 时,才用 crossorigin="use-credentials",且服务端必须返回 Access-Control-Allow-Credentials: true 和明确域名的 Access-Control-Allow-Origin(不能是 *)。
哈希值必须从线上真实响应体生成
本地 npm 安装的文件、构建产物、别人页面抄来的哈希、甚至在线工具(如 srihash.org)算出的值,只要和浏览器最终请求到的字节流不一致,SRI 就失败。CDN 可能重定向、返回 gzip/Brotli 压缩内容、插入 BOM、或按 User-Agent 返回不同版本,这些都会影响哈希。
可靠命令是:
curl -sL https://cdn.jsdelivr.net/npm/vue@3.4.21/dist/vue.global.js | openssl dgst -sha384 -binary | openssl base64 -A
关键点:
-
-sL:静默 + 跟随重定向 - openssl 默认对解压后明文哈希,与浏览器行为完全一致
-
-A:防止 base64 输出换行符,否则integrity值非法
只对特定标签生效,其他写法全部忽略
SRI 是 W3C 规范限定机制,仅作用于 HTML 解析阶段的静态标签,且只支持两类:
<script src="" integrity="" crossorigin="anonymous"></script><link rel="stylesheet" href="" integrity="" crossorigin="anonymous">
以下情况浏览器直接忽略 integrity 属性,不报错也不校验:
- 内联脚本(
<script>console.log()</script>) -
<img>、<iframe>、<video>、<link rel="icon"> -
document.createElement('script')后手动设src和integrity -
fetch()、import()加载的模块
校验失败时没有 onerror,脚本被静默丢弃
SRI 失败不会触发 onerror 事件,也不会执行脚本或加载样式表。控制台只提示一句:
Failed to find a valid digest in the 'integrity' attribute(哈希格式错误或缺失 crossorigin)
或
The resource <url> was blocked because integrity check failed(校验启动但不匹配)
前者容易误判为网络问题,后者才是真被拦截。真正难的是确保每次上线的哈希都绑定到那个精确字节流——构建工具差异、CDN 压缩策略、BOM 插入、Node.js 版本导致的 base64 编码微小偏差,都会让哈希漂移。别依赖一次生成长期复用,把它当成构建流水线里必须跑通的一环。

















