共用方式為


為 ASP.NET Core Blazor 強制執行內容安全性原則

注意

這不是這篇文章的最新版本。 如需目前的版本,請參閱 本文的 .NET 9 版本。

警告

不再支援此版本的 ASP.NET Core。 如需詳細資訊,請參閱 .NET 和 .NET Core 支持原則。 如需目前的版本,請參閱 本文的 .NET 9 版本。

重要

這些發行前產品的相關資訊在產品正式發行前可能會有大幅修改。 Microsoft 對於此處提供的資訊,不做任何明示或暗示的保證。

如需目前的版本,請參閱 本文的 .NET 9 版本。

本文說明如何使用內容安全策略 (CSP) 搭配 ASP.NET Core Blazor 應用程式,協助防範特定類型的惡意攻擊,例如 跨網站腳本 (XSS)點擊劫持 攻擊。 XSS 是一種安全性弱點,其中網路攻擊者會將一或多個惡意的用戶端腳本放入應用程式的轉譯內容中。 在點擊劫持攻擊中,使用者被欺騙,與嵌入了您的應用程式的誘餌網站互動。

CSP(內容安全政策)藉由告知瀏覽器哪些是有效的,協助防範這些類型的攻擊:

  • 載入內容的來源,包括指令碼、樣式表、影像和外掛程式。
  • 頁面所採取的動作,指定表單允許的 URL 目標。
  • 當您的應用程式可以透過 <frame><iframe><object><embed> 標籤內嵌至另一個網站時。

建議您在實作 CSP 時閱讀下列 MDN 資源:

若要將 CSP 套用至應用程式,開發人員會在一或多個 標頭或 Content-Security-Policy 標籤中指定數個 CSP 內容安全性指示詞<meta>。 如需在啟動時在 C# 程式碼中將 CSP 套用至應用程式的指引,請參閱本文稍後的 ASP.NET Core Blazor 啟動frame-ancestors 指令 一節。

載入頁面時,瀏覽器會評估原則。 瀏覽器會檢查頁面的來源,並判斷其是否符合內容安全性指示詞的需求。 當政策指令未被滿足時,瀏覽器不會載入資源。 例如,請考慮不允許協力廠商指令碼的原則。 當頁面在 <script> 屬性中包含具有協力廠商來源的 src 標籤時,瀏覽器會防止指令碼載入。

大部分新式桌面和行動瀏覽器都支援 CSP,包括 Chrome、Edge、Firefox、Opera 和 Safari。 建議針對 Blazor 應用程式使用 CSP。

警告

實作 CSP 可將特定安全性威脅類型的風險降到最低,且不保證應用程式完全安全不受 XSS 和點擊攔截攻擊。 使用者代理程式通常是瀏覽器,可讓使用者透過使用者喜好設定、書籤、瀏覽器延伸模組、使用者代理程式的第三方新增等機制來修改或略過原則強制執行。 此外,CSP 只會專注於補救攻擊的子集,並非所有可能危害安全性的攻擊,例如 SQL 插入式攻擊、跨網站要求偽造(CSRF)、安全性設定錯誤,以及拒絕服務 (DoS) 攻擊。

政策指令

下列指示詞和來源通常用於 Blazor 應用程式。 根據需要添加其他指導方針和來源。 本文 套用原則 一節中會使用下列指示詞,其中會提供 Blazor 應用程式的範例安全策略:

  • base-uri:限制頁面 <base> 標籤的 URL。 指定 self 以指出應用程式的來源,包括配置和連接埠號碼,是有效的來源。
  • default-src:表示對原則未明確指定之來源指令進行的後援。 指定 self 以指出應用程式的來源,包括配置和連接埠號碼,是有效的來源。
  • img-src:表示影像的有效來源。
    • 指定 data: 以允許從 data: URL 載入影像。
    • 指定 https: 以允許從 HTTPS 端點載入影像。
  • object-src:表示 <object><embed><applet> 標記的有效來源。 指定 none 以防止所有 URL 來源。
  • script-src:指出腳本的有效來源。
    • 指定 self 以指出應用程式的來源,包括配置和連接埠號碼,是有效的來源。
    • 在用戶端 Blazor 應用程式中:
      • 指定 wasm-unsafe-eval 以允許用戶端 Blazor Mono 執行階段運作。
      • 指定任何額外的雜湊值以允許載入您所需的非框架腳本。 例如,指定 unsafe-hashes 並使用 sha256-qnHnQs7NjQNHHNYv/I9cW+I62HzDJjbnyS/OFzqlix0= 的哈希值,以允許在 NavMenu 元件中使用導覽切換器的嵌入式 JavaScript。
    • 在伺服器端 Blazor 應用程式中,指定雜湊以允許載入所需的指令碼。
  • style-src:表示樣式表單的有效來源。
    • 指定 self 以指出應用程式的來源,包括配置和連接埠號碼,是有效的來源。
    • 如果應用程式使用內嵌樣式,請指定 unsafe-inline 以允許使用您的內嵌樣式。
  • connect-src:限制可以使用腳本介面載入的URL。 會指定配置來源 http:ws: (WebSocket 通訊協定)和 wss: (WebSocket Secure 通訊協定)。
  • upgrade-insecure-requests:表示應透過 HTTPS 安全地取得來自不安全 (HTTP) 來源的內容 URL。
  • base-uri:限制頁面 <base> 標籤的 URL。 指定 self 以指出應用程式的來源,包括配置和連接埠號碼,是有效的來源。
  • default-src:表示對原則未明確指定之來源指令進行的後援。 指定 self 以指出應用程式的來源,包括配置和連接埠號碼,是有效的來源。
  • img-src:表示影像的有效來源。
    • 指定 data: 以允許從 data: URL 載入影像。
    • 指定 https: 以允許從 HTTPS 端點載入影像。
  • object-src:表示 <object><embed><applet> 標記的有效來源。 指定 none 以防止所有 URL 來源。
  • script-src:指出腳本的有效來源。
    • 指定 self 以指出應用程式的來源,包括配置和連接埠號碼,是有效的來源。
    • 在用戶端 Blazor 應用程式中:
      • 指定 unsafe-eval 以允許用戶端 Blazor Mono 執行階段運作。
      • 指定任何額外的雜湊值以允許載入您所需的非框架腳本
    • 在伺服器端 Blazor 應用程式中,指定雜湊以允許載入所需的指令碼。
  • style-src:表示樣式表單的有效來源。
    • 指定 self 以指出應用程式的來源,包括配置和連接埠號碼,是有效的來源。
    • 如果應用程式使用內嵌樣式,請指定 unsafe-inline 以允許使用您的內嵌樣式。
  • connect-src:限制可以使用腳本介面載入的URL。 會指定配置來源 http:ws: (WebSocket 通訊協定)和 wss: (WebSocket Secure 通訊協定)。
  • upgrade-insecure-requests:表示應透過 HTTPS 安全地取得來自不安全 (HTTP) 來源的內容 URL。
  • base-uri:限制頁面 <base> 標籤的 URL。 指定 self 以指出應用程式的來源,包括配置和連接埠號碼,是有效的來源。
  • default-src:表示對原則未明確指定之來源指令進行的後援。 指定 self 以指出應用程式的來源,包括配置和連接埠號碼,是有效的來源。
  • img-src:表示影像的有效來源。
    • 指定 data: 以允許從 data: URL 載入影像。
    • 指定 https: 以允許從 HTTPS 端點載入影像。
  • object-src:表示 <object><embed><applet> 標記的有效來源。 指定 none 以防止所有 URL 來源。
  • script-src:指出腳本的有效來源。
    • 指定 Bootstrap 指令碼的 https://stackpath.bootstrapcdn.com/ 主機來源。
    • 指定 self 以指出應用程式的來源,包括配置和連接埠號碼,是有效的來源。
    • 在用戶端 Blazor 應用程式中:
      • 指定 unsafe-eval 以允許用戶端 Blazor Mono 執行階段運作。
      • 指定任何額外的雜湊值以允許載入您所需的非框架腳本
    • 在伺服器端 Blazor 應用程式中,指定雜湊以允許載入所需的指令碼。
  • style-src:表示樣式表單的有效來源。
    • 指定 https://stackpath.bootstrapcdn.com/ Bootstrap 樣式表的主機來源。
    • 指定 self 以指出應用程式的來源,包括配置和連接埠號碼,是有效的來源。
    • 指定 unsafe-inline 以允許使用內嵌樣式。
  • connect-src:限制可以使用腳本介面載入的URL。 會指定配置來源 http:ws: (WebSocket 通訊協定)和 wss: (WebSocket Secure 通訊協定)。
  • upgrade-insecure-requests:表示應透過 HTTPS 安全地取得來自不安全 (HTTP) 來源的內容 URL。
  • base-uri:限制頁面 <base> 標籤的 URL。 指定 self 以指出應用程式的來源,包括配置和連接埠號碼,是有效的來源。
  • default-src:表示對原則未明確指定之來源指令進行的後援。 指定 self 以指出應用程式的來源,包括配置和連接埠號碼,是有效的來源。
  • img-src:表示影像的有效來源。
    • 指定 data: 以允許從 data: URL 載入影像。
    • 指定 https: 以允許從 HTTPS 端點載入影像。
  • object-src:表示 <object><embed><applet> 標記的有效來源。 指定 none 以防止所有 URL 來源。
  • script-src:指出腳本的有效來源。
    • 指定 Bootstrap 指令碼的 https://stackpath.bootstrapcdn.com/ 主機來源。
    • 指定 self 以指出應用程式的來源,包括配置和連接埠號碼,是有效的來源。
    • 在用戶端 Blazor 應用程式中:
      • 指定哈希以允許載入所需的指令碼。
      • 指定 unsafe-eval 以使用 eval() 和方法以從字串建立程式碼。
    • 在伺服器端 Blazor 應用程式中,指定雜湊以允許載入所需的指令碼。
  • style-src:表示樣式表單的有效來源。
    • 指定 https://stackpath.bootstrapcdn.com/ Bootstrap 樣式表的主機來源。
    • 指定 self 以指出應用程式的來源,包括配置和連接埠號碼,是有效的來源。
    • 指定 unsafe-inline 以允許使用內嵌樣式。 為了在初始請求後重新連接用戶端和伺服器,UI 需要具備內嵌聲明。 在未來版本中,可能會移除內嵌樣式,因而不再需要 unsafe-inline
  • connect-src:限制可以使用腳本介面載入的URL。 會指定配置來源 http:ws: (WebSocket 通訊協定)和 wss: (WebSocket Secure 通訊協定)。
  • upgrade-insecure-requests:表示應透過 HTTPS 安全地取得來自不安全 (HTTP) 來源的內容 URL。

除了 Microsoft Internet Explorer 之外,所有瀏覽器都支援上述指示詞。

若要取得其他內嵌指令碼的 SHA 雜湊:

  • 套用原則區段中套用所顯示的 CSP。
  • 在本機執行應用程式時,存取瀏覽器的開發人員工具主控台。 當 CSP 標頭或 meta 標籤存在時,瀏覽器會計算並顯示封鎖指令碼的雜湊。
  • 將瀏覽器提供的雜湊值複製到相應的 script-src 來源。 在每個哈希周圍使用單引號。

如需內容安全性原則層級 2 瀏覽器支援矩陣,請參閱我是否可以使用:內容安全性原則層級 2

套用政策

您可以透過下列方式套用 CSP:

  • 主機發出的響應標頭(例如 IIS)或應用程式發出的回應標頭(請參閱在啟動時的 C# 程式代碼中 控件標頭)。
  • <meta> 標籤。 本文只會示範 <meta> 標記方法。

若要使用 <meta> 標籤來套用原則:

  • http-equiv 屬性值設定為 Content-Security-Policy
  • 將指示詞放在 content 屬性值中。 以分號 (;) 分隔指示詞。 根據 內容安全政策層級 3 的規範,政策字串的最後一個指示不需要有結尾的分號。
  • <meta> 標籤放在 <head> 內容中, 位於開頭 <head> 標籤標內。 在剖析 CSP 標記時,會評估並強制執行原則,因此原則應該出現在 <head> 標記頂端,以確保在所有 <script><link> 標記上強制執行。

下列各節顯示範例原則。 這些範例會隨著本文版本一起發佈於 Blazor 的每個發行版本中。 若要使用適合您版本的版本,請使用此網頁上的 [版本] 下拉式選取器選取文件版本。

frame-ancestors 指令

frame-ancestors 指令指定可以內嵌包含 <frame><iframe><object><embed> 標記的頁面的有效的父元素。 frame-ancestors 指令無法透過 <meta> 標籤型 CSP 套用。 指令必須透過回應標頭來套用。 伺服器主機可以新增 CSP 回應標頭,或應用程式 C# 程式代碼可以使用 frame-ancestors 指示詞來新增或更新 CSP。

Blazor Web Apps (.NET 8 或更新版本)會自動包含將值設定為 'self'的回應標頭:

Content-Security-Policy: frame-ancestors 'self'

若要將預設值變更為更嚴格的 'none' 並防止所有父系嵌入應用程式,請在 Program 檔案中設定對 AddInteractiveServerRenderMode 的呼叫的 ContentSecurityFrameAncestorsPolicy 選項。 以下內容僅會在啟用 WebSocket 壓縮時生效(已設定<xref:Microsoft.AspNetCore.Components.Server.ServerComponentsEndpointOptions.ConfigureWebSocketAcceptContext%2A>,這是 Blazor 應用程式的預設設定)。

.AddInteractiveServerRenderMode(o => o.ContentSecurityFrameAncestorsPolicy = "'none'")

在 Blazor Server 應用程式中,預設 frame-ancestors 指示詞不會新增至響應標頭集合。 您可以使用要求處理管線中的 中間件,手動新增 CSP 標頭:

app.Use(async (context, next) =>
{
    context.Response.Headers.Add("Content-Security-Policy", "frame-ancestors 'none'");
    await next();
});

警告

避免在啟用 WebSocket 壓縮(壓縮是預設值)時將 frame-ancestors 指令值設為 'null',因為這會使應用程式容易受到惡意腳本插入和點擊攔截的攻擊。

如需詳細資訊,請參閱 CSP:框架祖系 (MDN 檔案)

伺服器端 Blazor 應用程式

下列範例是進一步開發的起點。 在 <head> 內容頂端,套用 原則指示詞 一節中所述的指示詞,以及應用程式規格所需的任何其他指示詞。

針對 Blazor Web App或 Blazor Server 應用程式:

<meta http-equiv="Content-Security-Policy" content="
    base-uri 'self';
    default-src 'self';
    img-src data: https:;
    object-src 'none';
    script-src 'self' 'wasm-unsafe-eval' 'unsafe-hashes' 
        'sha256-qnHnQs7NjQNHHNYv/I9cW+I62HzDJjbnyS/OFzqlix0=';
    style-src https:;
    connect-src 'self' http: ws: wss:;
    upgrade-insecure-requests;" />

Blazor Web App包含 NavMenu 元件中的內嵌 onclick JavaScript 事件處理程式,需要進行下列其中一種變更:

  • 使用 unsafe-hashes 關鍵詞,將哈希新增至 script-src 指示詞:

    'unsafe-hashes' 'sha256-qnHnQs7NjQNHHNYv/I9cW+I62HzDJjbnyS/OFzqlix0='
    

    如需詳細資訊,請參閱 CSP:script-src:不安全的內嵌腳本 (MDN 檔案)

  • 將內嵌 JavaScript 事件處理程式移至原則允許載入的 JavaScript 檔案或模組。

Blazor Web App在 <head> 內容中也包含 ImportMap 元件,呈現一個內嵌匯入地圖 <script> 標記。 要修改政策以允許導入映射載入,請參閱 使用子資源完整性 (SRI) 或加密隨機數 (nonce) 解析 CSP 違規 一節。

針對 Blazor Server 應用:

<meta http-equiv="Content-Security-Policy" content="
    base-uri 'self';
    default-src 'self';
    img-src data: https:;
    object-src 'none';
    script-src 'self';
    style-src 'self';
    connect-src 'self' http: ws: wss:;
    upgrade-insecure-requests">

針對 Blazor Server 應用程式:

<meta http-equiv="Content-Security-Policy" content="
    base-uri 'self';
    default-src 'self';
    img-src data: https:;
    object-src 'none';
    script-src 'self' https://stackpath.bootstrapcdn.com/;
    style-src 'self' 'unsafe-inline' https://stackpath.bootstrapcdn.com/;
    connect-src 'self' http: ws: wss:;
    upgrade-insecure-requests">

針對 Blazor Server 應用程式:

<meta http-equiv="Content-Security-Policy" content="
    base-uri 'self';
    default-src 'self';
    img-src data: https:;
    object-src 'none';
    script-src 'self' https://stackpath.bootstrapcdn.com/ 
        'sha256-34WLX60Tw3aG6hylk0plKbZZFXCuepeQ6Hu7OqRf8PI=';
    style-src 'unsafe-inline' https://stackpath.bootstrapcdn.com/;
    connect-src 'self' http: ws: wss:;
    upgrade-insecure-requests">

注意

上述SHA256哈希僅供示範之用。 您可能需要計算 CSP 的新哈希。

根據應用程式的需求,新增額外的 script-srcstyle-src 雜湊。 在開發期間,使用線上工具或瀏覽器開發人員工具來計算雜湊值。 例如,下列瀏覽器工具主控台錯誤會報告原則未涵蓋之必要指令碼的雜湊:

拒絕執行內嵌指令碼,因為它違反下列內容安全性原則指示詞:" ... "。 需要 'unsafe-inline' 關鍵字、雜湊 ('sha256-v8v3RKRPmN4odZ1CWM5gw80QKPCCWMcpNeOmimNL2AA=') 或 nonce ('nonce-...') 才能啟用內嵌程式碼執行。

與錯誤相關聯的特定指令碼會顯示在錯誤旁邊的主控台中。

如需在啟動時將 CSP 套用至 C# 程式碼中應用程式的指導,請參閱 ASP.NET Core Blazor 啟動

用戶端 Blazor 應用程式

下列範例是進一步開發的起點。 在 <head> 內容中,套用在政策指示一節中所述的指令:

<meta http-equiv="Content-Security-Policy" content="
    base-uri 'self';
    default-src 'self';
    img-src data: https:;
    object-src 'none';
    script-src 'self' 'wasm-unsafe-eval';
    style-src 'self';
    connect-src 'none';
    upgrade-insecure-requests">
<meta http-equiv="Content-Security-Policy" content="
    base-uri 'self';
    default-src 'self';
    img-src data: https:;
    object-src 'none';
    script-src 'self' 'unsafe-eval';
    style-src 'self';
    connect-src 'none';
    upgrade-insecure-requests">
<meta http-equiv="Content-Security-Policy" content="
    base-uri 'self';
    default-src 'self';
    img-src data: https:;
    object-src 'none';
    script-src 'self' 'unsafe-eval' 
        'sha256-v8v3RKRPmN4odZ1CWM5gw80QKPCCWMcpNeOmimNL2AA=';
    style-src 'self';
    connect-src 'none';
    upgrade-insecure-requests">

註記

sha256-v8v3RKRPmN4odZ1CWM5gw80QKPCCWMcpNeOmimNL2AA= 雜湊代表用於用戶端應用程式的內嵌指令碼。 這可能會在未來移除。

<meta http-equiv="Content-Security-Policy" content="
    base-uri 'self';
    default-src 'self';
    img-src data: https:;
    object-src 'none';
    script-src 'self' 'unsafe-eval' https://stackpath.bootstrapcdn.com/ 
        'sha256-v8v3RKRPmN4odZ1CWM5gw80QKPCCWMcpNeOmimNL2AA=';
    style-src 'self' 'unsafe-inline' https://stackpath.bootstrapcdn.com/;
    upgrade-insecure-requests">
<meta http-equiv="Content-Security-Policy" content="
    base-uri 'self';
    default-src 'self';
    img-src data: https:;
    object-src 'none';
    script-src 'self' 'unsafe-eval' https://stackpath.bootstrapcdn.com/ 
        'sha256-v8ZC9OgMhcnEQ/Me77/R9TlJfzOBqrMTW8e1KuqLaqc=' 
        'sha256-If//FtbPc03afjLezvWHnC3Nbu4fDM04IIzkPaf3pH0=' 
        'sha256-v8v3RKRPmN4odZ1CWM5gw80QKPCCWMcpNeOmimNL2AA=';
    style-src 'self' 'unsafe-inline' https://stackpath.bootstrapcdn.com/;
    upgrade-insecure-requests">

根據應用程式的需求,新增額外的 script-srcstyle-src 雜湊。 在開發期間,使用線上工具或瀏覽器開發人員工具來為您計算雜湊值。 例如,下列瀏覽器工具主控台錯誤會報告原則未涵蓋之必要指令碼的雜湊:

拒絕執行內嵌指令碼,因為它違反下列內容安全性原則指示詞:" ... "。 需要 'unsafe-inline' 關鍵字、雜湊 ('sha256-v8v3RKRPmN4odZ1CWM5gw80QKPCCWMcpNeOmimNL2AA=') 或 nonce ('nonce-...') 才能啟用內嵌程式碼執行。

與錯誤相關聯的特定指令碼會顯示在錯誤旁邊的主控台中。

使用子資源完整性(SRI)或加密隨機數解決內容安全政策(CSP)違規

解決 CSP 違規的兩種方法,如下兩節所述:

採用子資源完整性 (SRI)

子資源完整性 (SRI) 可讓瀏覽器確認所擷取的資源不會在傳輸中遭到竄改。 資源上提供的密碼編譯哈希必須符合瀏覽器針對所擷取的資源和 CSP 中列出的哈希所計算的哈希。 在 Can I use? 中可以評估瀏覽器相容性,子資源完整性

在下列 Blazor Server 應用程式的範例中,會使用第三方工具來計算完整性,並針對 Blazor 腳本 (blazor.server.js) 和 CSP 指定。 Blazor 腳本在此案例中不會動態變更,而且具有穩定的SHA哈希,因此您可以硬式編碼 integrity 屬性值。

謹慎

️ ⚠在從不同來源載入的子資源上設定 crossorigin 屬性,而不需 跨原始來源資源分享 (CORS)。 如果應用程式的來源與子資源載入的來源不同,則需要 Access-Control-Allow-Origin 標頭來允許資源與要求的來源 共用,否則必須將 crossorigin 屬性套用到應用程式中的子資源標籤。 否則,瀏覽器會針對子資源採用「失敗開啟」原則,這表示子資源會載入而不檢查其完整性。

下列範例中不會將 crossorigin 屬性新增至 Blazor<script> 標籤,因為 Blazor 腳本是從應用程式的來源載入。

如需詳細資訊,請參閱 跨原始來源資源分享和子資源完整性 (MDN 檔案)

<!DOCTYPE html>
<html lang="en">
<head>
    <meta http-equiv="Content-Security-Policy" content="
        base-uri 'self';
        default-src 'self';
        img-src data: https:;
        object-src 'none';
        script-src 'sha256-FyuamsHhg0nWZUnu/f5qrt2DlL1XKt5AX+cgRhtxtfg=';
        style-src https:;
        connect-src 'self' http: ws: wss:;
        upgrade-insecure-requests;" />
    ...
</head>
<body>
    ...
    <script src="_framework/blazor.server.js" 
        integrity="sha256-FyuamsHhg0nWZUnu/f5qrt2DlL1XKt5AX+cgRhtxtfg="></script>
</body>
</html>

在下列範例中,Blazor Web App (.NET 8 或更新版本)會計算 ImportMap 元件 (.NET 9 或更新版本) 的完整性。 每個應用程式要求都會計算 ImportMap 完整性值,因為每次為指紋資產生成頁面時,ImportMap 元件都會呈現唯一的內容。

ImportMap 元件轉譯的匯入對應是由應用程式在其起始點產生的,因此 crossorigin 屬性 並未包含在 ImportMap 標籤中。 如需詳細資訊,請參閱 MDN CSP 指南:哈希子資源完整性 (MDN 檔)

@using System.Security.Cryptography
<!DOCTYPE html>
<html lang="en">
<head>
    <meta http-equiv="Content-Security-Policy" content="
        base-uri 'self';
        default-src 'self';
        img-src data: https:;
        object-src 'none';
        script-src 'self' 'wasm-unsafe-eval' 'unsafe-hashes' '@integrity'
            'sha256-qnHnQs7NjQNHHNYv/I9cW+I62HzDJjbnyS/OFzqlix0=';
        style-src https:;
        connect-src 'self' http: ws: wss:;
        upgrade-insecure-requests;" />
    ...
    <ImportMap integrity="@integrity" />
    ...
</head>
...
</html>

@code {
    private string? integrity;

    [CascadingParameter]
    public HttpContext? HttpContext { get; set; }

    protected override void OnInitialized()
    {
        var metadata = HttpContext?.GetEndpoint()?.Metadata
            .GetOrderedMetadata<ImportMapDefinition>();
        var utf8 = new System.Text.UTF8Encoding();
        var metadataBytes = utf8.GetBytes(
            metadata?.FirstOrDefault<ImportMapDefinition>()?.ToString()
                .ReplaceLineEndings("\n") ?? string.Empty);
        integrity = 
            $"sha256-{Convert.ToBase64String(SHA256.HashData(metadataBytes))}";
    }
}

在 .NET 6 之前,請使用 .Replace("\r\n", "\n"),而不是在上述程式代碼中呼叫 ReplaceLineEndings

注意

如果需要在 ImportMap 元件的渲染 <script> 元素上加上額外的屬性,可以將所有屬性的字典傳入 ImportMap 元件裡的 AdditionalAttributes 屬性。 integrity 屬性名稱/值組會與其他額外屬性一起被傳入字典裡。

採用密碼學中的 nonce

密碼隨機數(一次使用的數字)可以讓瀏覽器確認擷取的資源不會在傳輸中被竄改。 CSP 中提供的單次使用密碼學隨機數必須與資源上指示的隨機數一致。 您可以在 "Can I use?" 網站上評估瀏覽器相容性。Nonce

在以下範例中,針對 Blazor Web App (.NET 8 或更新版本),每次載入應用程式時,會為 ImportMap 元件 (.NET 9 或更新版本) 建立一個具有獨特值的 nonce。

如需詳細資訊,請參閱 MDN CSP 指南:「Nonces」CSP:「script-src:不安全內嵌腳本」(MDN 文檔)

@using System.Security.Cryptography
<!DOCTYPE html>
<html lang="en">
<head>
    <meta http-equiv="Content-Security-Policy" content="
        base-uri 'self';
        default-src 'self';
        img-src data: https:;
        object-src 'none';
        script-src 'self' 'wasm-unsafe-eval' 'unsafe-hashes' 'nonce-@nonce' 
            'sha256-qnHnQs7NjQNHHNYv/I9cW+I62HzDJjbnyS/OFzqlix0=';
        style-src https:;
        connect-src 'self' http: ws: wss:;
        upgrade-insecure-requests;" />
    ...
    <ImportMap nonce="@nonce" />
    ...
</head>
...
</html>

@code {
    private string? nonce;

    protected override void OnInitialized()
    {
        using (var rng = RandomNumberGenerator.Create())
        {
            var nonceBytes = new byte[32];
            rng.GetBytes(nonceBytes);
            nonce = Convert.ToBase64String(nonceBytes);
        }
    }
}

注意

如果需要在 ImportMap 元件所轉譯的 <script> 元素上添加其他屬性,您可以將包含所有屬性的字典傳遞到 ImportMap 元件的 AdditionalAttributes 屬性中。 nonce 名稱/值組會與其他傳遞屬性的其餘部分一起傳入字典中。

在非 Development 環境中套用 CSP

當 CSP 套用至 Blazor 應用程式的 <head> 內容時,會干擾 Development 環境中的本機測試。 例如,瀏覽器連結與瀏覽器重新整理指令碼無法載入。 下列範例示範如何在非 <meta> 環境中套用 CSP 的 Development 標記。

備註

本節中的範例不會顯示 CSP 的完整 <meta> 標記。 完整 <meta> 標記位於本文稍早套用原則一節的子區段中。

有三種一般方法可供使用:

  • 透過 App 元件套用 CSP,以將 CSP 套用至應用程式的所有配置。
  • 如果您需要將 CSP 套用至應用程式的不同區域,例如只有系統管理員頁面的自訂 CSP,請使用 <HeadContent> 標籤,依配置套用 CSP。 為了獲得完整的有效性,每個應用程式配置檔案都必須採用方法。
  • 代管服務或伺服器可以透過 Content-Security-Policy 標頭,在應用程式的傳出回應中提供 CSP。 由於此方法會因裝載服務或伺服器而異,因此不會在下列範例中說明。 如果您想要採用此方法,請參閱裝載服務提供者或伺服器的文件。

Blazor Web App 方法

App 元件 (Components/App.razor) 中,插入 IHostEnvironment

@inject IHostEnvironment Env

當不在 App 環境中時,在 <head> 元件的 Development 內容中套用 CSP:

@if (!Env.IsDevelopment())
{
    <meta ...>
}

或者,在 Components/Layout 資料夾中依個別配置套用 CSP,如下列範例所示。 請確定每個配置都會指定 CSP。

@inject IHostEnvironment Env

@if (!Env.IsDevelopment())
{
    <HeadContent>
        <meta ...>
    </HeadContent>
}

Blazor WebAssembly 應用程式策略

App 元件 (App.razor) 中,插入 IWebAssemblyHostEnvironment

@using Microsoft.AspNetCore.Components.WebAssembly.Hosting
@inject IWebAssemblyHostEnvironment Env

當不在 App 環境中時,在 <head> 元件的 Development 內容中套用 CSP:

@if (!Env.IsDevelopment())
{
    <HeadContent>
        <meta ...>
    </HeadContent>
}

或者,使用上述程式碼,但在 Layout 資料夾中依個別配置套用 CSP。 請確定每個配置都會指定 CSP。

後設標籤限制

<meta> 標籤原則不支援下列指令:

若要支援上述指示詞,請使用名為 Content-Security-Policy 的標頭。 指令字串是標頭的值。

測試原則並接收違規報告

測試有助於確認建置初始原則時,協力廠商指令碼不會不小心被阻擋。

若要在一段時間內測試原則,而不強制執行原則指示詞,請將 <meta> 標籤的 http-equiv 屬性或標頭式原則的標頭名稱設定為 Content-Security-Policy-Report-Only。 失敗報告會以 JSON 文件的形式傳送至指定的 URL。 如需詳細資訊,請參閱 MDN Web 文件:僅限內容安全性原則報告

如需在原則作用中時報告違規情況,請參閱下列文章:

雖然不再建議使用 report-uri,但應該使用這兩個指示詞,直到所有主要瀏覽器都支援 report-to 為止。 請勿專門使用 report-uri,因為對 report-uri 的支援可能會隨時從瀏覽器卸除。 當完全支援 report-uri 時,請移除原則中的 report-to 支援。 若要追蹤 report-to 的採用情況,請參閱可否使用:report-to

測試並更新每個版本的應用程式原則。

疑難排解

  • 錯誤會出現在瀏覽器的開發人員工具主控台中。 瀏覽器提供下列相關資訊:
    • 不符合原則的元素。
    • 如何修改原則以允許封鎖的項目。
  • 只有在用戶端的瀏覽器支援所有內含指示詞時,原則才完全有效。 如需目前的瀏覽器支援矩陣,請參閱我是否可以使用:內容安全性原則

其他資源