加了 integrity 却未拦截篡改,主因是缺失 crossorigin="anonymous" 或 CDN 未返回 Access-Control-Allow-Origin: *;多 CDN 场景下还易因压缩差异、重定向、无效标签(如 as="image")等导致 SRI 失效。

加了 integrity 却没拦住被篡改的 CSS 或 JS,大概率不是 CDN 被劫持了,而是你漏掉了 crossorigin="anonymous",或者 CDN 没返回 Access-Control-Allow-Origin: * —— 这两个条件缺一,校验就静默跳过,资源照常加载,控制台连 warning 都没有。
为什么多 CDN 场景下 integrity 更容易失效
多个 CDN(比如 https://css.cdn.com、https://js.cdn.com、https://fonts.cdn.com)意味着更多响应头和内容协商变数。常见翻车点:
-
integrity值是用本地文件或未压缩版算的,但 CDN 实际返回的是 Brotli 压缩后、带 BOM、末尾多空格的版本 —— 哈希必然不匹配 - 某个 CDN(如老旧镜像站)压根不返回
Access-Control-Allow-Origin,导致浏览器拿不到响应体,SRI 根本无法启动 - CDN 开启了 302 重定向(比如从
/v1/app.css跳到/v1.2.3/app.css),浏览器对跳转后的 URL 做哈希比对,而你算的是原始 URL 的内容 - 你给
<link rel="preload" as="image">加了integrity—— 它不支持 SRI,写了等于白写
integrity 只对哪些 <link> 生效
浏览器只认三种组合,其他全忽略:
-
<link rel="stylesheet" href="..." integrity="..." crossorigin="anonymous">✅ -
<link rel="preload" as="font" href="..." integrity="..." crossorigin="anonymous">✅(字体支持 SRI) -
<link rel="preload" as="script" href="..." integrity="..." crossorigin="anonymous">✅(脚本预加载也支持) -
<link rel="icon">、<link rel="preload" as="image">、<link as="style">❌ 全部无效,不校验也不报错
特别注意:<link rel="stylesheet"> 是唯一常用且必须配 integrity 的样式链路;as="font" 和 as="script" 预加载虽支持,但实际业务中极少需要校验预加载资源本身。
立即学习“前端免费学习笔记(深入)”;
生成可靠 integrity 值的实操要点
别信本地文件、别抄别人页面、别依赖在线工具——唯一可信路径是直取 CDN 响应体:
- 用
curl -sL https://css.cdn.com/main.css获取真实响应(-L自动跟随重定向,-s静默) - 哈希算法优先选
sha384:抗碰撞更强,jsDelivr、unpkg、cdnjs全支持;sha512浏览器不认,写了也无效 - 命令示例:
curl -sL https://css.cdn.com/main.css | openssl dgst -sha384 -binary | openssl base64 -A - 输出结果必须是
sha384-开头 + Base64 字符串(不是 hex),例如:sha384-oqVuAfXRKap7fdgcCY5uykM6+R9GqQ8K/uxy9rx7HNQlGYl1kPzQho1wx4JwY8wC
生成后务必手动测试:把 integrity 值临时删掉一位,刷新页面,确认控制台出现 The resource was blocked because integrity check failed —— 这才说明机制真在起作用。
多 CDN 下 crossorigin 配置的兼容性陷阱
crossorigin 不是可选项,是 SRI 的强制开关:
-
crossorigin="anonymous":最安全通用,不带 cookie,要求 CDN 返回Access-Control-Allow-Origin: *(公开 CDN 都满足) -
crossorigin="use-credentials":仅当你自己的后端需鉴权访问静态资源时才用,此时 CDN 必须返回Access-Control-Allow-Origin: https://your-site.com+Access-Control-Allow-Credentials: true,否则请求直接失败 -
crossorigin=""在 Chrome 中等价于anonymous,但 Firefox 解析更严格,建议统一写死为crossorigin="anonymous" - 拼写错误如
crossorigin="true"、CROSSORIGIN、crossorigin="ANONYMOUS"都会导致校验静默失效
真正容易被忽略的是:SRI 失效时,页面不会崩溃,也不会抛异常,只是脚本或样式不加载 —— 白屏、样式错乱、功能缺失,但控制台只有极窄的一条 warning,很容易被淹没。上线前必须做破坏性验证。



















