integrity值必须从线上真实响应体计算,不可用本地文件;需用curl -sL URL | openssl dgst -sha384 -binary | openssl base64 -A生成,并配合crossorigin="anonymous"和Access-Control-Allow-Origin响应头才能生效。

integrity 值必须从线上真实响应体计算,不是本地文件
本地 cat 或 npm install 后的 CSS 文件算出的哈希,99% 会失效。CDN 可能返回压缩版、重定向到不同 URL、按 UA 返回不同内容、甚至插入 BOM —— 这些都会让字节流和你本地文件不一致。
真正有效的哈希,只能源自浏览器最终请求到的原始响应体。比如你写的是:<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css">,那哈希就必须基于这个 URL 实际返回的字节流生成。
- 用
curl -sL跟随重定向并静默获取内容(-sL不可省) - 确保管道不引入额外换行或空格(
openssl base64 -A必须带-A) - 别用在线生成器(如 srihash.org),它们不模拟真实 CDN 响应链
命令行生成 integrity 的标准写法(推荐 sha384)
sha384 是当前兼容性与安全性最平衡的选择,主流 CDN(jsDelivr/unpkg/cdnjs)默认支持。执行以下命令即可得到可用值:
curl -sL https://cdn.jsdelivr.net/npm/bootstrap@5.3.3/dist/css/bootstrap.min.css | openssl dgst -sha384 -binary | openssl base64 -A
输出形如:sha384-7X3zZJ1QqVcK0vYtUaWwDdFmQx2fSgI+RkPbXjE3MhT1iOZyCQ==
立即学习“前端免费学习笔记(深入)”;
-
-sha384:算法必须和integrity前缀一致,不能混用sha256-前缀配 sha384 计算结果 -
-binary:告诉 openssl 输出二进制哈希,而非 hex 字符串 -
-A:强制 base64 单行输出,避免换行符污染 integrity 值(漏掉它会导致Failed to find a valid digest)
link 标签必须同时满足三个硬性条件才触发校验
只写 integrity 属性,浏览器压根不启动 SRI。必须三者齐备:
-
rel="stylesheet"(不能是rel="icon"或rel="preload") - 合法的
integrity值(格式正确、base64 编码、前缀匹配) - 显式声明
crossorigin="anonymous"(crossorigin=""在 Firefox 中可能被忽略)
缺一即静默跳过——资源照常加载,控制台连 warning 都没有。你只会看到样式没生效、控制台孤零零一条 The resource was blocked because integrity check failed,或者更隐蔽的 Failed to find a valid digest(说明校验根本没跑起来)。
常见翻车点:哈希对了,但校验还是失败
哈希本身正确,不代表 SRI 就能生效。这些细节容易被忽略:
- CDN 没返回
Access-Control-Allow-Origin: *(公开 CDN)或明确域名(use-credentials场景),浏览器拿不到完整响应体,SRI 直接无法启动 - 用了
crossorigin="use-credentials",但服务端没返回Access-Control-Allow-Credentials: true和对应域名的Access-Control-Allow-Origin(*不允许) - 在
file://协议下打开 HTML:SRI 全面禁用,所有属性都无效 - 标签写成
<link as="style">或<link rel="preload" as="style">:SRI 不支持,写了也白搭
最稳妥的做法:先确认该 URL 在浏览器地址栏直接访问时,响应头含 Access-Control-Allow-Origin,且 Network 面板中该请求状态码为 200、Size 显示“from cache”或具体字节数(而非 “(blocked)”)。否则,integrity 再准也没意义。



















