子资源完整性 (SRI) 是一项安全功能,可让浏览器验证从 CDN 或第三方来源获取的资源是否未被篡改。在供应链攻击的时代——英国航空公司 Magecart 漏洞、Polyfill.io 泄露以及众多 CDN 事件——SRI 提供加密保证,确保您的页面加载的资源正是您想要的。
社会责任投资如何运作
当您将 integrity 属性添加到 <script> 或 <link rel="stylesheet"> 标记时,浏览器会计算所获取资源的哈希值并将其与属性值进行比较。如果它们不匹配,浏览器将拒绝执行或应用该资源。
<script
src="https://cdn.example.com/library.js"
integrity="sha384-oqVuAfXRKap7fdgcCY5uykM6+R9GqQ8K/uxy9rx7HNQlGYl1kPzQho1wx4JwY8wC"
crossorigin="anonymous"
></script>
当资源的多个版本可接受时,多个哈希(逗号分隔)允许优雅的回退:
<script
src="https://cdn.example.com/app.js"
integrity="sha384-ABC... sha512-XYZ..."
crossorigin="anonymous"
></script>
跨源资源上的 SRI 需要 crossorigin="anonymous" 属性。如果没有正确的 CORS 标头,浏览器会以不透明模式加载资源,并且无法验证其完整性 - 该资源会被静默忽略,不会出现任何错误。
生成 SRI 哈希值
您可以使用 OpenSSL、在线工具或构建时插件生成 SRI 哈希值:
# OpenSSL command
openssl dgst -sha384 -binary file.js | openssl base64 -A
为了实现自动化,请将 SRI 生成集成到您的构建管道中。构建工具支持成熟:
| 工具 | 插件/配置 |
|---|---|
| 网页包 | 占位符_0 |
| 维特 | vite-plugin-sri 或通过 experimental.renderBuiltUrl 内置 |
| Next.js | next.config.js 中的 experimental.sri |
| 天文 | 资产组件上内置 integrity 属性 |
// Next.js SRI configuration
// next.config.js
module.exports = {
experimental: {
sri: {
hash: "sha384",
},
},
};
确保在缩小和生成源映射后计算哈希值 - 哈希值必须与最终提供的内容匹配,而不是与开发源匹配。
SRI 和 CSP 相关性
内容安全策略和 SRI 相辅相成。 CSP限制哪些来源可以加载资源; SRI 确保来自允许来源的资源未被修改。它们相结合,为第三方资源加载提供深度防御。
<!-- CSP header -->
Content-Security-Policy:
script-src https://cdn.example.com 'sha384-oqVuAfXRKap7fdgcCY5uykM6+R9GqQ8K/uxy9rx7HNQlGYl1kPzQho1wx4JwY8wC';
report-uri https://reporting.example.com/csp-violations
<!-- HTML with SRI -->
<script
src="https://cdn.example.com/library.js"
integrity="sha384-oqVuAfXRKap7fdgcCY5uykM6+R9GqQ8K/uxy9rx7HNQlGYl1kPzQho1wx4JwY8wC"
crossorigin="anonymous"
></script>
使用 CSP 的 report-uri 或 report-to 指令来监视 SRI 违规。不匹配的哈希可能表明 CDN 受损、构建管道问题或中间件进行的内容转换。
监控 SRI 违规行为和高级模式
侦听具有完整性属性的元素上的 error 事件,或使用报告 API 从浏览器收集 SRI 违规报告:
// Client-side SRI violation monitoring
document.querySelectorAll("script[integrity]").forEach((el) => {
el.addEventListener("error", (event) => {
fetch("/api/sri-violation", {
method: "POST",
body: JSON.stringify({
src: el.src,
integrity: el.getAttribute("integrity"),
timestamp: new Date().toISOString(),
}),
});
});
});
CDN 提供商在 SRI 支持方面有所不同。验证您的 CDN 的功能:
| CDN | SRI 支持 | 笔记 |
|---|---|---|
| cdnjs | 完整 | 为所有库提供哈希值 |
| jsDelivr | 完整 | 包 API 响应中的哈希值 |
| 联合国包装袋 | 通过 ?meta | 可通过查询参数获取哈希值 |
| Google 托管库 | 部分 | 仅适用于受支持的库 |
高级 SRI 模式包括用户交互后加载的脚本的动态验证、Web Worker 的 SRI (new Worker("script.js", { integrity: "..." })) 以及 ES 模块分片的导入映射条目的完整性。
// Dynamic SRI verification for runtime-loaded scripts
async function loadWithIntegrity(url, integrity) {
const response = await fetch(url);
const buffer = await response.arrayBuffer();
const hash = await crypto.subtle.digest("SHA-384", buffer);
const base64 = btoa(String.fromCharCode(...new Uint8Array(hash)));
if (base64 !== integrity.replace("sha384-", "")) {
throw new Error("Integrity check failed");
}
// Execute the script safely
const blob = new Blob([buffer], { type: "text/javascript" });
const blobUrl = URL.createObjectURL(blob);
const script = document.createElement("script");
script.src = blobUrl;
document.body.appendChild(script);
}
实施回退策略:使用 SRI 从主 CDN 加载,如果完整性验证失败,则回退到自托管副本。即使 CDN 遭到破坏或内容发生更改,这也可确保您的应用程序保持正常运行。
SRI 是一项易于实现的关键安全控制:生成哈希、添加完整性属性、配置 CORS 标头以及在 CI 中自动生成哈希。结合CSP,为第三方资源加载提供强有力的保护。将 SRI 添加到所有外部资源、自动化流程并主动监控故障。

