子資源完整性 (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 新增至所有外部資源、自動化流程並主動監控故障。

