sri需csp与cors协同生效:csp的script-src须显式授权cdn域名,cdn响应头必须含access-control-allow-origin,且integrity哈希仅支持sha256-/sha384-前缀,三者缺一不可。

单纯加 integrity 属性无法防御 CDN 被篡改——浏览器根本不会校验,除非你同时满足 CSP 和 CORS 两个硬性前提。
为什么加了 integrity 却没报错也没拦截?
常见错误现象是:资源照常加载、控制台无任何 SRI 相关警告,哪怕你手动修改 CDN 返回的 JS 内容,浏览器也完全不拦。这通常是因为资源请求没走 CORS 模式。
原因很直接:integrity 触发校验的前提是浏览器能拿到完整响应体,而跨域资源默认不暴露 body(只暴露 status 和 headers)。CDN 必须返回 Access-Control-Allow-Origin: * 或明确允许你的域名,否则校验直接跳过。
- 即使没写
crossorigin属性,只要带integrity,浏览器也会强制以crossorigin="anonymous"发起请求 - 但若 CDN 不支持 CORS(比如某些老旧镜像站),请求会降级为不带 CORS 的普通请求,此时
integrity形同虚设 - 用
curl -I https://cdn.example.com/lib.js检查响应头,确认存在Access-Control-Allow-Origin
CSP 的 script-src 必须显式包含 CDN 域名
很多人以为 SRI 自己就能拦住篡改,其实它只负责“校验”,CSP 才负责“放行”。如果 CSP 策略里没列 CDN 域名,浏览器连请求都不会发出去——根本轮不到 SRI 校验。
例如这个策略:Content-Security-Policy: script-src 'self',哪怕你写了 integrity,浏览器也会直接拒绝加载 https://cdn.jsdelivr.net 的脚本,控制台报 Refused to load script from 'https://cdn.jsdelivr.net'。
- 正确写法是:
script-src 'self' https://cdn.jsdelivr.net https://cdn.example.com - 不要用通配符
https:,它不被现代浏览器支持(Chrome 94+ 已弃用) - 如果 CDN 支持子域名泛解析(如
cdn1.example.com,cdn2.example.com),可用https://*.example.com,但需确保所有子域名都配了 CORS
integrity 哈希算法必须与 CSP 的 require-sri-for 兼容
如果你在 CSP 头里加了 require-sri-for script,那所有外链 <script></script> 都强制要求带 integrity,否则直接阻断。但这里有个隐藏坑:CSP 默认只认 SHA-256 和 SHA-384,不接受 SHA-512。
比如你用 openssl dgst -sha512 -binary file.js | openssl base64 -A 生成了 SHA-512 哈希,再拼成 integrity="sha512-xxx",浏览器会忽略该属性,且不报错——它就当没这回事。
- 生产环境只用
sha256-或sha384-前缀,别碰sha512- - 生成命令推荐用 Node.js 内置 crypto:
node -e "console.log('sha384-'+require('crypto').createHash('sha384').update(require('fs').readFileSync('./file.js')).digest('base64'))" -
require-sri-for只对script和style有效,不作用于img或font
SRI 和 CSP 是两道独立但必须咬合的齿轮:CSP 控制“能不能发请求”,SRI 控制“收到的内容对不对”。漏掉 CORS 响应头、写错 CSP 白名单、或用了不被支持的哈希算法,三者任一出问题,整套机制就失效——而且失效时往往悄无声息,连控制台都不提醒。











