加了integrity却没拦住篡改脚本,大概率是crossorigin未配对或哈希未基于真实响应体生成;SRI仅对<script>和<link rel="stylesheet">生效,且integrity与crossorigin必须同时存在,缺一则校验静默失效。

加了 integrity 却没拦住篡改的脚本?大概率是 crossorigin 没配对,或者哈希值根本不是从真实响应体算出来的。
为什么 integrity 单独写没用
浏览器只在 <script> 和 <link rel="stylesheet"> 标签上执行 SRI 校验,且必须同时存在 integrity 和 crossorigin 属性——缺一不可。漏掉 crossorigin 不会报错,但校验直接被跳过,资源照常加载,integrity 形同虚设。
-
crossorigin="anonymous"是绝大多数公共 CDN(如 jsDelivr、cdn.jsdelivr.net)的正确取值,不带 Cookie 发起请求 -
crossorigin="use-credentials"仅当你自己的后端要求鉴权访问静态资源时才用,且后端必须返回Access-Control-Allow-Credentials: true和明确的Access-Control-Allow-Origin(不能是*) - 写成
crossorigin=""等价于anonymous,但 Firefox 解析更严格,建议统一写crossorigin="anonymous"
哈希值必须从真实 URL 响应体生成
本地文件、网页里写的路径、甚至你手动下载保存的 JS/CSS,都可能和 CDN 实际返回的内容不一致:gzip 压缩、BOM 头、重定向跳转、CDN 缓存策略导致的编码差异,都会让哈希失效。
- 用这条命令生成(确保行为与浏览器一致):
curl -sL https://cdn.jsdelivr.net/npm/react@18.2.0/umd/react.production.min.js | openssl dgst -sha384 -binary | openssl base64 -A -
-sL表示静默 + 跟随重定向,拿到浏览器最终加载的响应体 - 算法优先选
sha384:比sha256抗碰撞更强,主流 CDN 默认支持 - 哈希值必须是 Base64 编码后的字符串,不是 hex;格式固定为
sha384-AbCdEf...
哪些标签写了 integrity 也白写
SRI 是 W3C 明确定义的机制,只作用于两类标签:<script> 和 <link rel="stylesheet">。其他所有写法都不触发校验。
立即学习“前端免费学习笔记(深入)”;
-
<img src="" integrity="">:浏览器完全忽略,不校验也不报错 -
<link rel="icon">或<link rel="preload">:不支持 -
<iframe src="">或fetch()动态加载:SRI 规范未覆盖 -
document.createElement('script')后手动设置src和integrity:浏览器不校验,只认 HTML 解析阶段的静态标签 - 内联脚本(
<script>console.log()</script>):integrity属性无效
校验失败时浏览器怎么表现
JS 失败:控制台报 Failed to find a valid digest in the 'integrity' attribute,脚本不执行,可能导致白屏或功能异常;CSS 失败:静默丢弃样式表,只在 Console 中以 warning 级别显示同一条消息(默认可能被过滤掉)。
- 注意检查网络面板中该资源的响应头是否含
Content-Encoding: gzip或br:SRI 校验基于解压后的原始字节,若你用未压缩文件算 hash,必然不匹配 - 确保你用于计算 hash 的文件,和线上 URL 返回内容完全一致(包括 BOM、换行符、末尾空格)
- 避免使用带 query 参数的 URL(如
?v=123):SRI 不校验 URL,只校验响应体;但若 CDN 缓存了不同版本,hash 就失效
最容易被忽略的是:哈希值必须对应真实响应体,而真实响应体可能受重定向、压缩、BOM、CDN 缓存策略影响——这些细节不验证清楚,SRI 就只是个摆设。



















