Featured image of post 子資源完整性:保護您的 CDN 依賴項Featured image of post 子資源完整性:保護您的 CDN 依賴項

子資源完整性:保護您的 CDN 依賴項

Web 安全性子資源完整性 (SRI) 的完整指南:雜湊生成、跨來源配置、建置時整合、CSP 關聯和監控。

子資源完整性 (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.jsnext.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-urireport-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 的功能:

CDNSRI 支援筆記
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 新增至所有外部資源、自動化流程並主動監控故障。