保護 ASP.NET Core 伺服器端 Blazor 應用程式
注意
這不是這篇文章的最新版本。 如需目前的版本,請參閱 本文的 .NET 9 版本。
警告
不再支援此版本的 ASP.NET Core。 如需詳細資訊,請參閱 .NET 和 .NET Core 支援原則。 如需目前版本,請參閱本文的 .NET 8 版本。
本文說明如何以 ASP.NET Core 應用程式的形式保護伺服器端 Blazor 應用程式。
為求安全,伺服器端 Blazor 應用程式的設定方式會與 ASP.NET Core 應用程式相同。 如需詳細資訊,請參閱 ASP.NET Core 安全性主題底下的文章。
只有在應用程式啟動時 (也就是應用程式第一次連線到 WebSocket 時) 才會建立驗證內容。 驗證內容會在線路的存留期內受到維護。 應用程式會每隔 30 分鐘,定期重新驗證使用者的驗證狀態。
如果應用程式必須擷取自訂服務的使用者,或回應使用者更新,請參閱伺服器端 ASP.NET Core Blazor 其他安全性案例。
Blazor 不同於傳統伺服器轉譯的 Web 應用程式,這些應用程式會在瀏覽每個分頁時,使用 Cookie 提出新的 HTTP 要求。 瀏覽事件期間會檢查驗證。 不過,不涉及 Cookie。 只有在對伺服器提出 HTTP 要求時,才會傳送 Cookie,這不是使用者在 Blazor 應用程式中瀏覽時發生的情況。 在瀏覽期間,會在線路內 Blazor 檢查使用者的驗證狀態,您可以使用重新驗證 AuthenticationStateProvider
](#additional-authentication-state-providers)隨時更新伺服器上的驗證狀態。
重要
不建議在瀏覽期間實作自訂 NavigationManager
來實現驗證確認。 如果應用程式必須在瀏覽期間執行自訂驗證狀態邏輯,請使用自訂 AuthenticationStateProvider
。
注意
本文中的程式碼範例採用 可為 Null 的參考型別 (NRT) 和 .NET 編譯器 Null 狀態靜態分析,這在 .NET 6 或更新版本的 ASP.NET Core 中受到支援。 以 ASP.NET Core 5.0 或更早版本為目標時,請從本文的範例中移除 Null 型別指定 (?
)。
敏感數據和認證的伺服器端安全性
在測試/預備和生產環境中,伺服器端 Blazor 程序代碼和 Web API 應該使用安全驗證流程,以避免在專案程式代碼或組態檔內維護認證。 在本機開發測試之外,建議您避免使用環境變數來儲存敏感數據,因為環境變數不是最安全的方法。 針對本機開發測試, 建議使用秘密管理員工具 來保護敏感數據。 如需詳細資訊,請參閱以下資源:
針對客戶端和伺服器端本機開發和測試,請使用 秘密管理員工具來 保護敏感性認證。
專案範本
遵循 Tooling for ASP.NET Core Blazor 中的指引,建立新的伺服器端 Blazor 應用程式。
在選擇伺服器端應用程式範本並設定專案之後,請在 [驗證類型] 底下選取應用程式的驗證:
- 無 (預設值):無驗證。
- 個別帳戶:使用者帳戶會使用 ASP.NET Core Identity 儲存在應用程式內。
- 無 (預設值):無驗證。
- 個別帳戶:使用者帳戶會使用 ASP.NET Core Identity 儲存在應用程式內。
- Microsoft identity 平台:如需詳細資訊,請參閱 ASP.NET Core Blazor驗證和授權。
- Windows:使用 Windows 驗證。
BlazorIdentity UI (個人帳戶)
當您選擇 [個別帳戶] 的驗證選項時,Blazor 支援產生完整 Blazor 型 Identity UI。
Blazor Web App 範本會為 SQL Server 資料庫產生 Identity 程式碼。 命令列版本會使用 SQLite,並包含 Identity 的 SQLite 資料庫。
範本:
- 有支援互動式伺服器端轉譯 (互動式 SSR),還有經驗證使用者的用戶端轉譯 (CSR) 案例。
- 新增 IdentityRazor 例行驗證工作的元件和相關邏輯,例如:登入和登出的使用者。這些 Identity 元件也支援進階 Identity 功能,例如使用第三方應用程式進行帳戶確認和密碼復原,還有多重要素驗證 。 請注意 Identity 元件本身暫不支持互動功能。
- 新增 Identity 相關的套件和相依性。
- 參考
_Imports.razor
中的 Identity 套件。 - 建立自訂使用者 Identity 類別 (
ApplicationUser
)。 - 建立及註冊 EF Core 資料庫內容 (
ApplicationDbContext
)。 - 設定內建 Identity 端點的路由。
- 包含 Identity 驗證和商務邏輯。
若要檢查 Blazor 架構的 Identity 元件,請到Pages
和 Shared
資料夾中存取,存放在Account
這個資料夾中,資料就存放在 Blazor Web App 專案範本 (參考來源) 那邊。
當您選擇互動式 WebAssembly 或互動式自動轉譯模式時,伺服器會處理所有驗證和授權要求,而 Identity 元件會在 Blazor Web App 的主要專案中透過靜態方式,呈現在伺服器上。
架構會在伺服器和用戶端 (.Client
) 專案中提供自訂 AuthenticationStateProvider,以將使用者的驗證狀態流向瀏覽器。 伺服器專案會呼叫 AddAuthenticationStateSerialization,而用戶端專案會呼叫 AddAuthenticationStateDeserialization。 在伺服器上進行驗證,而不是用戶端允許應用程式在預先轉譯期間,以及在初始化 NET WebAssembly 執行階段之前存取驗證狀態。 自訂 AuthenticationStateProvider 實作會使用保存元件狀態服務 (PersistentComponentState) 將驗證狀態序列化為 HTML 註解,然後從 WebAssembly 讀取它以建立新的 AuthenticationState 執行個體。 如需詳細資訊,請參閱在 Blazor Web App 中管理驗證狀態這個章節。
僅適用於互動式伺服器解決方案,IdentityRevalidatingAuthenticationStateProvider
(參考來源) 是伺服器端 AuthenticationStateProvider,連線互動式線路時,每 30 分鐘會重新驗證已連線使用者的安全性戳記。
當您選擇互動式 WebAssembly 或互動式自動轉譯模式時,伺服器會處理所有驗證和授權要求,而 Identity 元件會在 Blazor Web App 的主要專案中透過靜態方式,呈現在伺服器上。 專案範本包含 .Client
專案中的 PersistentAuthenticationStateProvider
類別 (參考來源),以同步處理伺服器與瀏覽器之間的使用者驗證狀態。 類別是 AuthenticationStateProvider 的自訂實作。 提供者會使用保存元件狀態服務 (PersistentComponentState),預先轉譯驗證狀態,並將其保存至頁面。
在 Blazor Web App 的主要專案中,驗證狀態供應器名為 IdentityRevalidatingAuthenticationStateProvider
(參考來源)(僅限伺服器互動功能解決方案)或 PersistingRevalidatingAuthenticationStateProvider
(參考來源)(WebAssembly 或自動互動功能解決方案)。
BlazorIdentity 取決於 DbContext 執行個體未由處理站建立,這是刻意的,因為 DbContext 足以讓專案範本的 Identity 元件以靜態方式轉譯,而不用支援互動功能。
如需在針對 Identity 元件強制執行靜態 SSR 的同時,全域互動轉譯模式如何套用至非 Identity 元件的描述,請參閱 ASP.NET Core Blazor 轉譯模式。
如需保存預先轉譯狀態的詳細資訊,請參閱預先轉譯 ASP.NET Core Razor 元件。
注意
.NET 參考來源的文件連結通常會載入存放庫的預設分支,這表示下一版 .NET 的目前開發。 若要選取特定版本的標籤,請使用 [切換分支或標籤] 下拉式清單。 如需詳細資訊,請參閱如何選取 ASP.NET Core 原始程式碼 (dotnet/AspNetCore.Docs #26205) 的版本標籤。
在 Blazor Web App 管理驗證狀態
本章節適用於 Blazor Web App會採用以下幾點:
- 個人帳戶
- 用戶端轉譯 (CSR,WebAssembly 型互動)。
用戶端驗證狀態供應器僅在 Blazor 內使用,不會與 ASP.NET Core 驗證系統整合。 在預先轉譯期間,Blazor 遵守頁面上定義的中繼資料,並且使用 ASP.NET Core 驗證系統來判斷使用者是否已驗證。 當使用者從一個頁面瀏覽到另一個頁面時,會使用用戶端驗證提供者。 當使用者重新整理頁面 (完整頁面重新載入) 時,用戶端驗證狀態供應器不會參與伺服器上的驗證決策。 由於伺服器不會保存使用者的狀態,因此維護用戶端的任何驗證狀態都會遺失。
若要解決此問題,最佳方法是在 ASP.NET Core 驗證系統中執行驗證。 用戶端驗證狀態供應器只會負責反映使用者的驗證狀態。 Blazor Web App 專案範本示範如何使用驗證狀態供應器來完成這項作業的範例,分述如下。
在伺服器專案的 Program
檔案中,呼叫 AddAuthenticationStateSerialization,其會使用保存元件狀態服務 (PersistentComponentState) 序列化伺服器端 AuthenticationStateProvider 傳回的 AuthenticationState:
builder.Services.AddRazorComponents()
.AddInteractiveWebAssemblyComponents()
.AddAuthenticationStateSerialization();
這些 API 只會序列化伺服器端名稱和角色宣告,以在瀏覽器中存取。 若要包含所有宣告,請將 SerializeAllClaims
設定為在伺服器端呼叫 AddAuthenticationStateSerialization 的 true
:
builder.Services.AddRazorComponents()
.AddInteractiveWebAssemblyComponents()
.AddAuthenticationStateSerialization(
options => options.SerializeAllClaims = true);
在用戶端 (.Client
) 專案的 Program
檔案中,呼叫 AddAuthenticationStateDeserialization,這會新增 AuthenticationStateProvider,其中會使用 AuthenticationStateData
和保存元件狀態服務 (PersistentComponentState) 從伺服器還原序列化 AuthenticationState。 伺服器專案中應該有對 AddAuthenticationStateSerialization 的對應呼叫。
builder.Services.AddAuthorizationCore();
builder.Services.AddCascadingAuthenticationState();
builder.Services.AddAuthenticationStateDeserialization();
PersistingRevalidatingAuthenticationStateProvider
(參考來源) :針對 Blazor Web App 採用互動式伺服器端轉譯 (互動式 SSR) 和用戶端轉譯 (CSR)。 這是伺服器端 AuthenticationStateProvider,連線互動性線路時,每 30 分鐘重新驗證已連線使用者的安全性戳記。 也會使用永續性元件狀態服務,將驗證狀態流向用戶端,接著針對 CSR 的存留期加以修正。PersistingServerAuthenticationStateProvider
(參考來源):會針對只有採用客戶服務代表 (CSR) 的 Blazor Web App。 這是伺服器端 AuthenticationStateProvider,使用永續性元件狀態服務,將驗證狀態流向用戶端,接著針對 CSR 的存留期加以修正。PersistentAuthenticationStateProvider
(參考來源)::會針對只有採用客戶服務代表 (CSR) 的 Blazor Web App。 這是用戶端 AuthenticationStateProvider,藉由尋找在伺服器上轉譯時保存在頁面中的資料,判斷使用者的驗證狀態。 此驗證狀態已針對 CSR 的存留期修正。 如果使用者需要登入或登出,則需要完整頁面重新載入。 這僅會提供使用者名稱和電子郵件以供顯示之用。 不包含在提出後續要求時向伺服器驗證的權杖,這會使用對伺服器提出的HttpClient
要求中包含的 cookie 個別處理。
注意
.NET 參考來源的文件連結通常會載入存放庫的預設分支,這表示下一版 .NET 的目前開發。 若要選取特定版本的標籤,請使用 [切換分支或標籤] 下拉式清單。 如需詳細資訊,請參閱如何選取 ASP.NET Core 原始程式碼 (dotnet/AspNetCore.Docs #26205) 的版本標籤。
產生Identity
如需如何將 Identity 產生至伺服器端 Blazor 應用程式的詳細資訊,請參閱在 ASP.NET Core 專案中產生 Identity。
來自外部提供者的其他宣告和權杖
若要儲存來自外部提供者的其他宣告,請參閱在 ASP.NET Core 中保存來自外部提供者的其他宣告和權杖。
Linux 上的 Azure App Service 與 Identity 伺服器
請在部署 Linux 上的 Azure App Service 與 Identity 伺服器時明確指定簽發者。 如需詳細資訊,請參閱使用 Identity 來保護 SPA 的 Web API 後端。
為範圍限定為元件的服務插入 AuthenticationStateProvider
請不要嘗試在自訂範圍內解析 AuthenticationStateProvider,因為其會導致為未正確初始化的 AuthenticationStateProvider 建立新執行個體。
若要在範圍限定為元件的服務內存取 AuthenticationStateProvider,請使用 @inject
指示詞或 [Inject]
屬性插入 AuthenticationStateProvider,並將其以參數形式傳遞至服務。 此方法確保針對每個使用者應用程式執行個體使用正確、初始化的 AuthenticationStateProvider 執行個體。
ExampleService.cs
:
public class ExampleService
{
public async Task<string> ExampleMethod(AuthenticationStateProvider authStateProvider)
{
var authState = await authStateProvider.GetAuthenticationStateAsync();
var user = authState.User;
if (user.Identity is not null && user.Identity.IsAuthenticated)
{
return $"{user.Identity.Name} is authenticated.";
}
else
{
return "The user is NOT authenticated.";
}
}
}
將服務註冊為範圍。 在伺服器端 Blazor 應用程式中,限定範圍服務的存留期等於用戶端連線線路的持續時間。
在 Program
檔案中:
builder.Services.AddScoped<ExampleService>();
在 Startup.cs
的 Startup.ConfigureServices
中:
services.AddScoped<ExampleService>();
在下列 InjectAuthStateProvider
元件中:
- 元件會繼承 OwningComponentBase。
- 插入 AuthenticationStateProvider 並傳遞至
ExampleService.ExampleMethod
。 ExampleService
會使用 OwningComponentBase.ScopedServices 和 GetRequiredService 進行解析,這會傳回使用者線路存留期中存在的正確、初始化ExampleService
執行個體。
InjectAuthStateProvider.razor
:
@page "/inject-auth-state-provider"
@inherits OwningComponentBase
@inject AuthenticationStateProvider AuthenticationStateProvider
<h1>Inject <code>AuthenticationStateProvider</code> Example</h1>
<p>@message</p>
@code {
private string? message;
private ExampleService? ExampleService { get; set; }
protected override async Task OnInitializedAsync()
{
ExampleService = ScopedServices.GetRequiredService<ExampleService>();
message = await ExampleService.ExampleMethod(AuthenticationStateProvider);
}
}
@page "/inject-auth-state-provider"
@inject AuthenticationStateProvider AuthenticationStateProvider
@inherits OwningComponentBase
<h1>Inject <code>AuthenticationStateProvider</code> Example</h1>
<p>@message</p>
@code {
private string? message;
private ExampleService? ExampleService { get; set; }
protected override async Task OnInitializedAsync()
{
ExampleService = ScopedServices.GetRequiredService<ExampleService>();
message = await ExampleService.ExampleMethod(AuthenticationStateProvider);
}
}
如需詳細資訊,請參閱 ASP.NET Core Blazor 相依性插入中 OwningComponentBase 的相關指引。
使用自訂 AuthenticationStateProvider
預先轉譯時會顯示未經授權的內容
若要避免在預先轉譯自訂 AuthenticationStateProvider
時顯示未經驗證的內容,例如 AuthorizeView
元件中的內容,請採用以下其中一個方法:
為自訂 AuthenticationStateProvider 實作 IHostEnvironmentAuthenticationStateProvider 以支援預先轉譯:如需 IHostEnvironmentAuthenticationStateProvider 的範例實作,請在
ServerAuthenticationStateProvider.cs
(參考來源) 中參閱 Blazor 架構的 ServerAuthenticationStateProvider 實作。注意
.NET 參考來源的文件連結通常會載入存放庫的預設分支,這表示下一版 .NET 的目前開發。 若要選取特定版本的標籤,請使用 [切換分支或標籤] 下拉式清單。 如需詳細資訊,請參閱如何選取 ASP.NET Core 原始程式碼 (dotnet/AspNetCore.Docs #26205) 的版本標籤。
停用預先轉譯:指出轉譯模式,其中
prerender
參數在應用程式元件階層的最高階元件中設定為false
,最高階元件不是根元件。注意
不支援讓根元件成為互動式,例如
App
元件。 因此,App
元件無法直接停用預先轉譯。針對以 Blazor Web App 專案範本為基礎的應用程式,通常會先停用預先轉譯,其中
Routes
元件的使用時機是應用到App
元件 (Components/App.razor
) 上:<Routes @rendermode="new InteractiveServerRenderMode(prerender: false)" />
此外,停用元件的
HeadOutlet
預先轉譯:<HeadOutlet @rendermode="new InteractiveServerRenderMode(prerender: false)" />
您也可以選擇性地控制套用至
Routes
元件執行個體的轉譯模式。 如需範例,請參閱 ASP.NET Core Blazor 轉譯模式。
- 在應用程式啟動前驗證伺服器上的使用者:若要採用這種方法,應用程式必須以 Identity 型登入頁面或檢視回應使用者的初始要求,並防止對 Blazor 端點的任何要求,直到其驗證完畢為止。 如需詳細資訊,請參閱使用受授權保護的使用者資料建立 ASP.NET Core 應用程式。 驗證之後,只有在使用者真正未經授權檢視內容時,才會顯示預先轉譯 Razor 元件中未經授權的內容。
使用者狀態管理
儘管名稱中有 "state" 這個字,但 AuthenticationStateProvider 不是用於儲存「一般使用者狀態」。 AuthenticationStateProvider 只會指出使用者對應用程式的驗證狀態、其是否登入應用程式,以及其以什麼身分登入。
驗證會使用與 Razor Pages 和 MVC 應用程式相同的 ASP.NET Core Identity 驗證。 針對 ASP.NET Core Identity 儲存的使用者狀態會流向 Blazor,而無需將額外的程式碼新增至應用程式。 請遵循 ASP.NET Core Identity 文章和教學課程中的指引,讓 Identity 功能在應用程式的 Blazor 組件中生效。
如需 ASP.NET Core Identity 以外的一般狀態管理指引,請參閱 ASP.NET Core Blazor 狀態管理。
其他驗證狀態提供者
衍生自 AuthenticationStateProvider 管理伺服器上驗證狀態的兩個額外類別:
ServerAuthenticationStateProvider(參考來源):當未註冊更特定的提供者時,架構用來Blazor管理伺服器上的驗證狀態的預設AuthenticationStateProvider。
RevalidatingServerAuthenticationStateProvider (參考來源):從主機環境接收驗證狀態的服務基類 AuthenticationStateProvider ,並定期重新驗證它。 如需範例實作, Blazor Web App 請參閱項目範本 。 覆寫 RevalidationInterval 以變更預設的 30 分鐘重新驗證間隔。
注意
.NET 參考來源的文件連結通常會載入存放庫的預設分支,這表示下一版 .NET 的目前開發。 若要選取特定版本的標籤,請使用 [切換分支或標籤] 下拉式清單。 如需詳細資訊,請參閱如何選取 ASP.NET Core 原始程式碼 (dotnet/AspNetCore.Docs #26205) 的版本標籤。
登出時的驗證狀態管理
伺服器端 Blazor 會在線路存留期內保存使用者驗證狀態,包括跨瀏覽器索引標籤。 當使用者在某一索引標籤登出時,若要跨瀏覽器索引標籤主動將使用者登出,您必須使用簡短的 RevalidationInterval 來實作 RevalidatingServerAuthenticationStateProvider (參考來源)。
注意
.NET 參考來源的文件連結通常會載入存放庫的預設分支,這表示下一版 .NET 的目前開發。 若要選取特定版本的標籤,請使用 [切換分支或標籤] 下拉式清單。 如需詳細資訊,請參閱如何選取 ASP.NET Core 原始程式碼 (dotnet/AspNetCore.Docs #26205) 的版本標籤。
暫時重新導向 URL 有效期間
本章節適用於 Blazor Web App。
針對 Blazor 伺服器端轉譯發出的暫時重新導向 URL,使用 RazorComponentsServiceOptions.TemporaryRedirectionUrlValidityDuration 選項來取得或設定 ASP.NET Core 資料保護有效性的存留期。 這些只是暫時使用,因此存留期只要足夠讓用戶端接收 URL 並開始瀏覽至該 URL 即可。 不過,也應該足以允許跨伺服器時發生的時鐘誤差。 預設值為五分鐘。
在下列範例中,該值會延長至七分鐘:
builder.Services.AddRazorComponents(options =>
options.TemporaryRedirectionUrlValidityDuration =
TimeSpan.FromMinutes(7));
其他資源
- 快速入門:透過 Microsoft 將登入新增至 ASP.NET Core Web 應用程式
- 快速入門:使用 Microsoft identity 平台來保護 ASP.NET Core Web API
- 設定 ASP.NET Core 以與 Proxy 伺服器和負載平衡器搭配運作:包含下列指引:
- 使用轉送的標頭中介軟體來跨 Proxy 伺服器和內部網路保留 HTTPS 配置資訊。
- 其他案例和使用案例,包括手動配置設定、正確要求路由的要求路徑變更,以及轉送 Linux 和非 IIS 反向 Proxy 的要求配置。