integrity属性能防cdn劫持,但仅当同时满足三个条件:资源为跨域的或、integrity值基于cdn实际响应体计算、且显式声明crossorigin="anonymous",缺一则校验静默失效。

integrity 属性真能防 CDN 劫持?先看它拦不拦得住
能,但只在满足三个硬性条件时才生效:资源必须是跨域加载的 <script></script> 或 <link rel="stylesheet">;integrity 值必须基于该 CDN 实际返回的响应体计算;且必须显式声明 crossorigin="anonymous"。漏掉任意一条,浏览器就当没这回事——既不报错,也不校验,劫持成功后脚本照常执行。
Failed to find a valid digest 是不是 CDN 被劫持了?
不一定。这个错误只说明浏览器尝试校验但没找到合法哈希格式,常见原因包括:
-
integrity值写错了前缀(比如写成SHA384-而不是小写的sha384-) - 哈希值本身是 hex 编码而非 base64(例如
sha256-abc123错,sha256-AbCdEf对) -
crossorigin属性缺失、拼错(如crossorigin="true")、或值不合法 - CDN 返回的响应头不含
Access-Control-Allow-Origin: *,导致 CORS 请求失败,浏览器拿不到响应体来算哈希
真正被劫持时,你看到的通常是 The resource <url> was blocked because integrity check failed</url> —— 这才是校验触发且不匹配的明确信号。
怎么生成一个不会翻车的 integrity 值?
别信本地文件、别抄别人页面、别依赖在线工具生成的“看起来对”的哈希。唯一可靠方式是用命令行直取 CDN 响应体:
curl -sL https://cdn.jsdelivr.net/npm/vue@3.4.21/dist/vue.global.js | openssl dgst -sha384 -binary | openssl base64 -A
关键点:
-
-sL:静默 + 跟重定向,避免哈希到 302 响应 - 不加
--compressed:curl默认自动解压 gzip/Brotli,返回的是浏览器实际拿到的字节 - BOM、末尾换行、空格都会破坏哈希,确保 CDN 返回的是干净 UTF-8 无 BOM 内容
- 优先选
sha384:比sha256抗碰撞更强,主流 CDN 全支持
crossorigin="anonymous" 为什么不能省?
因为 SRI 校验强制走 CORS 流程。没有 crossorigin,浏览器根本不会把响应体暴露给校验逻辑——它连内容都读不到,自然无法比对哈希。这不是 bug,是规范设计:安全机制必须建立在可验证的传输通道上。
绝大多数公开 CDN(jsDelivr、unpkg、cdnjs)都返回 Access-Control-Allow-Origin: *,所以 crossorigin="anonymous" 就够用。只有当你自己的后端要求带 Cookie 加载静态资源时,才考虑 crossorigin="use-credentials",但此时服务端必须同步返回 Access-Control-Allow-Credentials: true 和明确域名的 Access-Control-Allow-Origin,否则请求直接失败。
最容易被忽略的是:校验失败时,脚本静默丢弃,不触发 onerror,也不抛异常。上线前务必手动改错一个字符测试拦截效果——否则你永远不知道它到底有没有在工作。
前端入门到VUE实战笔记:立即使用
在学习笔记中,你将探索 前端 的入门与实战技巧!











