ASP.NET Core Blazor 驗證與授權
注意
這不是這篇文章的最新版本。 如需目前的版本,請參閱 本文的 .NET 9 版本。
警告
不再支援此版本的 ASP.NET Core。 如需詳細資訊,請參閱 .NET 和 .NET Core 支持原則。 如需目前的版本,請參閱 本文的 .NET 9 版本。
本文說明 ASP.NET Core 對於在 Blazor 應用程式中設定及管理安全性的支援。
Blazor 會使用現有的 ASP.NET Core 驗證機制來建立使用者的 identity。 確切的機制會取決於 Blazor 應用程式的裝載方式 (伺服器端或用戶端)。
在 Blazor 應用程式中,伺服器端和用戶端所執行的授權碼是不同的安全性情境。 若是在伺服器上執行的授權碼,授權檢查可針對應用程式和元件的區域強制執行存取規則。 由於用戶端的程式碼執行可能會遭到竄改,因此無法保證在用戶端上執行的授權碼會絕對強制執行存取規則或控制用戶端內容的顯示。
如果必須確保授權規則的強制執行,請勿將授權檢查實作於用戶端程式碼中。 只會仰賴伺服器端轉譯 (SSR) 進行授權檢查,並強制執行規則,即可組建 Blazor Web App。
如果必須確保授權規則強制執行以及資料與程式碼的安全性,請勿開發用戶端應用程式。 建置 Blazor Server 應用程式。
Razor Pages 授權慣例不會套用至路由式 Razor 元件。 如果非路由 Razor 元件內嵌在 Razor 網頁應用程式 的分頁中,分頁的授權慣例會間接影響到 Razor 元件,還有網頁的 rest 內容。
ASP.NET Core Identity 的設計目的是要在 HTTP 要求和回應通訊的情境中運作,而這通常並不是 Blazor 應用程式的用戶端-伺服器通訊模型。 使用 ASP.NET Core Identity 來管理使用者的 ASP.NET Core 應用程式,應該使用 Razor Pages 而非 Razor 元件來取得 Identity 相關 UI,例如使用者註冊、登入、登出和其他使用者管理工作。 建置直接處理 Identity 工作的 Razor 元件在數個案例中是可行的,但 Microsoft 不建議這麽做亦不提供支援。
Razor 元件不支援 ASP.NET Core 抽象概念,例如 SignInManager<TUser> 和 UserManager<TUser>。 如需搭配使用 ASP.NET Core Identity 與 Blazor 的詳細資訊,請參閱 將 ASP.NET Core Identity 搭建到伺服器端 Blazor應用程式中。
注意
本文中的程式碼範例採用 可為 Null 的參考型別 (NRT) 和 .NET 編譯器 Null 狀態靜態分析,這在 .NET 6 或更新版本的 ASP.NET Core 中受到支援。 以 ASP.NET Core 5.0 或更早版本為目標時,請從本文的範例中移除 Null 型別指定 (?
)。
安全地維護敏感數據和認證
請勿在用戶端程式代碼中儲存應用程式秘密、連接字串、認證、密碼、個人標識碼 (PIN)、私人 .NET/C# 程式代碼或私鑰/令牌,這一律不安全。 Blazor用戶端程式代碼應該透過您控制的安全 Web API 來存取安全的服務和資料庫。
在測試/預備和生產環境中,伺服器端 Blazor 程序代碼和 Web API 應該使用安全驗證流程,以避免在專案程式代碼或組態檔內維護認證。 在本機開發測試之外,建議您避免使用環境變數來儲存敏感數據,因為環境變數不是最安全的方法。 針對本機開發測試, 建議使用秘密管理員工具 來保護敏感數據。 如需詳細資訊,請參閱以下資源:
針對客戶端和伺服器端本機開發和測試,請使用 秘密管理員工具來 保護敏感性認證。
Microsoft Azure 服務的受控識別
針對 Microsoft Azure 服務,我們建議使用 受控識別。 受控識別可以以安全的方式向 Azure 服務進行驗證,而無需在應用程式程式碼中儲存認證。 如需詳細資訊,請參閱以下資源:
- 什麼是 Azure 資源受控識別? (Microsoft Entra 文件)
- Azure 服務文件
Antiforgery 支援
Blazor 範本:
- 當在
Program
檔案中呼叫 AddRazorComponents 時,系統會自動新增防偽服務。 - 新增防偽中介軟體,方法是在
Program
檔案中的要求處理管線中呼叫 UseAntiforgery,並要求端點防偽保護,以減輕跨網站要求偽造 (CSRF/XSRF) 的威脅。 UseAntiforgery 在之後 UseHttpsRedirection呼叫 。 UseAntiforgery如果呼叫存在,UseAuthentication則必須在呼叫 和 UseAuthorization之後進行呼叫。
AntiforgeryToken 元件會將 Antiforgery 權杖轉譯為隱藏欄位,而此元件會自動新增至表單 (EditForm) 執行個體。 如需詳細資訊,請參閱 ASP.NET Core Blazor 表單概觀。
AntiforgeryStateProvider 服務會提供與目前工作階段相關聯之 Antiforgery 權杖的存取權。 插入服務並呼叫其 GetAntiforgeryToken() 方法來取得目前的 AntiforgeryRequestToken。 如需詳細資訊,請參閱 從 ASP.NET Core Blazor 應用程式呼叫 Web API。
Blazor 會將要求權杖儲存在元件狀態中,這可確保互動式元件可以使用 Antiforgery 權杖,即使它們沒有要求的存取權也一樣。
注意
只有在將表單資料提交至編碼為 application/x-www-form-urlencoded
、multipart/form-data
或 text/plain
的伺服器時,才需要防偽移轉,因為只有這些是有效的表單編碼類型。
如需詳細資訊,請參閱以下資源:
- 防止在 ASP.NET Core 中出現跨網站偽造要求 (XSRF/CSRF) 攻擊:這篇文章正是本篇主要 ASP.NET Core 文章的主題,適用於伺服器端 Blazor Server、Blazor Web App 伺服器專案,以及將 Blazor 整合至 MVC/Razor 網頁。
- ASP.NET Core Blazor 表單概觀:關於 Blazor 表單防偽支援文章的防偽支援一節。
伺服器端 Blazor 驗證
為求安全,伺服器端 Blazor 應用程式的設定方式會與 ASP.NET Core 應用程式相同。 如需詳細資訊,請參閱 ASP.NET Core 安全性主題底下的文章。
只有在應用程式啟動時才會建立驗證內容,也就是應用程式第一次透過SignalR用戶端連線連線到 WebSocket 時。 驗證可以依據 cookie 或其他持有人權杖,但驗證會透過 SignalR 中樞並完全在 線路 內進行管理。 驗證內容會在線路的存留期內受到維護。 應用程式會每隔 30 分鐘,定期重新驗證使用者的驗證狀態。
如果應用程式必須擷取使用者以進行自定義服務或回應使用者的更新,請參閱 ASP.NET Core 伺服器端和其他 Blazor Web App 安全性案例。
Blazor 不同於傳統伺服器轉譯的 Web 應用程式,這些應用程式會在瀏覽每個分頁時,使用 Cookie 提出新的 HTTP 要求。 瀏覽事件期間會檢查驗證。 不過,不涉及 Cookie。 只有在對伺服器提出 HTTP 要求時,才會傳送 Cookie,這不是使用者在 Blazor 應用程式中瀏覽時發生的情況。 瀏覽期間,會在 Blazor 線路內檢查使用者的驗證狀態,您可以使用 RevalidatingAuthenticationStateProvider
抽象隨時在伺服器上更新。
重要
不建議在瀏覽期間實作自訂 NavigationManager
來實現驗證確認。 如果應用程式必須在瀏覽期間執行自訂驗證狀態邏輯,請使用自訂 AuthenticationStateProvider
。
注意
本文中的程式碼範例採用 可為 Null 的參考型別 (NRT) 和 .NET 編譯器 Null 狀態靜態分析,這在 .NET 6 或更新版本的 ASP.NET Core 中受到支援。 以 ASP.NET Core 5.0 或更早版本為目標時,請從本文的範例中移除 Null 型別指定 (?
)。
內建或自訂 AuthenticationStateProvider 服務會從 ASP.NET Core 的 HttpContext.User 那邊取得驗證狀態資料。 這就是驗證狀態與現有 ASP.NET Core 驗證機制之間的整合方式。
如需伺服器端驗證的詳細資訊,請參閱 ASP.NET 核心 Blazor 驗證和授權。
Razor 元件中的 IHttpContextAccessor
/HttpContext
IHttpContextAccessor 必須避免使用互動式轉譯,因為沒有有效的 HttpContext
可用。
IHttpContextAccessor 可用於伺服器上靜態轉譯的元件。 不過,建議您盡可能避免。
只能在一般工作的靜態轉譯根元件中將 HttpContext 用作 級聯參數,例如檢查和修改 App
元件 (Components/App.razor
) 中的標頭或其他屬性。 用於互動式轉譯的值一律是 null
。
[CascadingParameter]
public HttpContext? HttpContext { get; set; }
針對互動式元件中所需 HttpContext 的案例,建議您透過伺服器的持續元件狀態來流動資料。 如需詳細資訊,請參閱 ASP.NET Core 伺服器端和其他 Blazor Web App 安全性案例。
請勿在伺服器端 Blazor 應用程式的 Razor 元件中直接或間接使用 IHttpContextAccessor/HttpContext。 Blazor 應用程式會在 ASP.NET Core 管線內容之外執行。 既不保證 HttpContext 在 IHttpContextAccessor 中可用,也不保證 HttpContext 會保留啟動了 Blazor 應用程式的內容。
建議在 Blazor 應用程式的初始轉譯期間,透過根元件參數將要求狀態傳遞給此應用程式。 或者,應用程式可以將資料複製到根元件初始化生命週期事件中的範圍服務,以便在整個應用程式中使用。 如需詳細資訊,請參閱 ASP.NET Core 伺服器端和其他 Blazor Web App 安全性案例。
伺服器端 Blazor 安全性的一個重要層面是,附加至指定線路的使用者可能會在建立 Blazor 線路後的某個時間點進行更新,但 IHttpContextAccessor不會更新。 如需使用自定義服務解決這種情況的詳細資訊,請參閱 ASP.NET Core 伺服器端和其他 Blazor Web App 安全性案例。
共用狀態
伺服器端 Blazor 應用程式位於伺服器記憶體中,且多個應用程式工作階段會裝載在相同的處理程序內。 針對每個應用程式工作階段,Blazor 會啟動具有其本身相依性插入容器範圍的線路,因此每個 Blazor 工作階段的範圍服務都是唯一的。
警告
除非非常小心,否則不建議使用單一資料庫服務在相同伺服器共用狀態上的應用程式,因為這可能會造成安全性弱點,例如跨線路洩漏使用者狀態。
如果應用程式特別針對它所設計,您可以在 Blazor 應用程式中使用具狀態單一資料庫服務。 例如,使用單一資料庫記憶體快取是可接受的,因為記憶體快取需要索引鍵才能存取指定的項目。 假設使用者無法控制與快取搭配使用的快取索引鍵,則儲存在快取中的狀態不會跨線路洩漏。
如需狀態管理的一般指導,請參閱 ASP.NET Core Blazor 狀態管理。
敏感數據和認證的伺服器端安全性
在測試/預備和生產環境中,伺服器端 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 元件。
如需 BlazorIdentity UI 的詳細資訊,並透過社交網站整合外部登入的指導,就請參閱 .NET 8 中 identity 的新功能。
注意
.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 狀態管理。
其他安全性抽象
有兩個額外的抽象會參與管理驗證狀態:
ServerAuthenticationStateProvider (參考來源):Blazor 架構用來從伺服器取得驗證狀態的 AuthenticationStateProvider。
RevalidatingServerAuthenticationStateProvider (參考來源):AuthenticationStateProvider 服務的基底類別,而 Blazor 架構會使用這些服務,從主機環境接收驗證狀態,並定期重新驗證。
預設 30 分鐘的重新驗證間隔可在
RevalidatingIdentityAuthenticationStateProvider
(Areas/Identity/RevalidatingIdentityAuthenticationStateProvider.cs
) 中進行調整。 下列範例會將間隔縮短為 20 分鐘:protected override TimeSpan RevalidationInterval => TimeSpan.FromMinutes(20);
注意
.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));
用戶端端 Blazor 驗證
在用戶端 Blazor 應用程式中,用戶端驗證檢查可以被略過,因為使用者可以修改所有用戶端端程式碼。 這同樣也適用於所有的用戶端端的應用程式技術,包括 JavaScript SPA 架構或任何作業系統的原生應用程式。
新增下列項目:
Microsoft.AspNetCore.Components.Authorization
NuGet 套件的套件參考。注意
如需將套件新增至 .NET 應用程式的指引,請參閱在套件取用工作流程 (NuGet 文件) 的安裝及管理套件底下的文章。 在 NuGet.org 確認正確的套件版本。
應用程式
_Imports.razor
檔案的 Microsoft.AspNetCore.Components.Authorization 命名空間。
若想處理驗證,請使用內建或自訂的 AuthenticationStateProvider 服務。
如需客戶端驗證的詳細資訊,請參閱 安全 ASP.NET Core Blazor WebAssembly的說明。
AuthenticationStateProvider
服務
AuthenticationStateProvider 是 AuthorizeView 元件和串聯驗證服務用來取得使用者驗證狀態的基礎服務。
AuthenticationStateProvider 是 AuthorizeView 元件與 CascadingAuthenticationState 元件用來取得使用者驗證狀態的基礎服務。
您通常不會直接使用 AuthenticationStateProvider。 請使用本文稍後所述的 AuthorizeView
元件或 Task<AuthenticationState>
方法。 使用 AuthenticationStateProvider 的主要缺點,在於系統不會在基礎驗證狀態資料變更時自動通知該元件。
若想執行自訂 AuthenticationStateProvider,請參閱 ASP.NET Core Blazor 驗證狀態,內容包含執行使用者驗證狀態的變更通知指南。
取得使用者的宣告主體資料
AuthenticationStateProvider 服務可以提供目前使用者的 ClaimsPrincipal 資料,如下列範例所示。
ClaimsPrincipalData.razor
:
@page "/claims-principal-data"
@using System.Security.Claims
@inject AuthenticationStateProvider AuthenticationStateProvider
<h1>ClaimsPrincipal Data</h1>
<button @onclick="GetClaimsPrincipalData">Get ClaimsPrincipal Data</button>
<p>@authMessage</p>
@if (claims.Any())
{
<ul>
@foreach (var claim in claims)
{
<li>@claim.Type: @claim.Value</li>
}
</ul>
}
<p>@surname</p>
@code {
private string? authMessage;
private string? surname;
private IEnumerable<Claim> claims = Enumerable.Empty<Claim>();
private async Task GetClaimsPrincipalData()
{
var authState = await AuthenticationStateProvider
.GetAuthenticationStateAsync();
var user = authState.User;
if (user.Identity is not null && user.Identity.IsAuthenticated)
{
authMessage = $"{user.Identity.Name} is authenticated.";
claims = user.Claims;
surname = user.FindFirst(c => c.Type == ClaimTypes.Surname)?.Value;
}
else
{
authMessage = "The user is NOT authenticated.";
}
}
}
在前述範例中:
- ClaimsPrincipal.Claims 會傳回使用者宣告 (
claims
) 以顯示在 UI 中。 - 取得使用者姓氏 (
surname
) 的行會使用述詞來呼叫 ClaimsPrincipal.FindAll,以篩選使用者的宣告。
@page "/claims-principal-data"
@using System.Security.Claims
@inject AuthenticationStateProvider AuthenticationStateProvider
<h1>ClaimsPrincipal Data</h1>
<button @onclick="GetClaimsPrincipalData">Get ClaimsPrincipal Data</button>
<p>@authMessage</p>
@if (claims.Any())
{
<ul>
@foreach (var claim in claims)
{
<li>@claim.Type: @claim.Value</li>
}
</ul>
}
<p>@surname</p>
@code {
private string? authMessage;
private string? surname;
private IEnumerable<Claim> claims = Enumerable.Empty<Claim>();
private async Task GetClaimsPrincipalData()
{
var authState = await AuthenticationStateProvider
.GetAuthenticationStateAsync();
var user = authState.User;
if (user.Identity is not null && user.Identity.IsAuthenticated)
{
authMessage = $"{user.Identity.Name} is authenticated.";
claims = user.Claims;
surname = user.FindFirst(c => c.Type == ClaimTypes.Surname)?.Value;
}
else
{
authMessage = "The user is NOT authenticated.";
}
}
}
如果 user.Identity.IsAuthenticated
為 true
,且由於使用者為 ClaimsPrincipal,系統便可以列舉宣告,並評估角色中的成員資格。
如需相依性插入 (DI) 和服務的詳細資訊,請參閱 ASP.NET Core Blazor 相依性插入和 ASP.NET Core 中的相依性插入。 如需索取關於如何執行自訂 AuthenticationStateProvider 的詳細資訊,請參閱 ASP.NET Core Blazor 驗證狀態說明。
將驗證狀態公開為階層式參數
如果程序性邏輯需要驗證狀態資料 (例如在執行由使用者觸發的動作時),請透過定義 Task<
AuthenticationState>
類型的階層式參數來取得驗證狀態資料,如下列範例所示。
CascadeAuthState.razor
:
@page "/cascade-auth-state"
<h1>Cascade Auth State</h1>
<p>@authMessage</p>
@code {
private string authMessage = "The user is NOT authenticated.";
[CascadingParameter]
private Task<AuthenticationState>? authenticationState { get; set; }
protected override async Task OnInitializedAsync()
{
if (authenticationState is not null)
{
var authState = await authenticationState;
var user = authState?.User;
if (user?.Identity is not null && user.Identity.IsAuthenticated)
{
authMessage = $"{user.Identity.Name} is authenticated.";
}
}
}
}
@page "/cascade-auth-state"
<h1>Cascade Auth State</h1>
<p>@authMessage</p>
@code {
private string authMessage = "The user is NOT authenticated.";
[CascadingParameter]
private Task<AuthenticationState>? authenticationState { get; set; }
protected override async Task OnInitializedAsync()
{
if (authenticationState is not null)
{
var authState = await authenticationState;
var user = authState?.User;
if (user?.Identity is not null && user.Identity.IsAuthenticated)
{
authMessage = $"{user.Identity.Name} is authenticated.";
}
}
}
}
如果 user.Identity.IsAuthenticated
為 true
,系統便可以列舉宣告,並評估角色中的成員資格。
使用 AuthorizeRouteView 和串聯驗證狀態服務設定 Task<
AuthenticationState>
串聯參數。
當您從其中一個已啟用驗證的 Blazor 專案範本建立 Blazor 應用程式時,此應用程式會包含上述範例中顯示的 AuthorizeRouteView 以及對 AddCascadingAuthenticationState 的呼叫。 用戶端端 Blazor 應用程式也包含必要的服務註冊。 使用 Router
元件來自訂未經授權內容章節中會顯示其他資訊。
<Router ...>
<Found ...>
<AuthorizeRouteView RouteData="routeData"
DefaultLayout="typeof(Layout.MainLayout)" />
...
</Found>
</Router>
在 Program
檔案中,註冊串聯驗證狀態服務:
builder.Services.AddCascadingAuthenticationState();
使用 AuthorizeRouteView 和 CascadingAuthenticationState 元件設定 Task<
AuthenticationState>
階層式參數。
當您從其中一個已啟用驗證的 Blazor 專案範本建立 Blazor 應用程式時,此應用程式會包含上述範例中顯示的 AuthorizeRouteView 和 CascadingAuthenticationState 元件。 用戶端端 Blazor 應用程式也包含必要的服務註冊。 使用 Router
元件來自訂未經授權內容章節中會顯示其他資訊。
<CascadingAuthenticationState>
<Router ...>
<Found ...>
<AuthorizeRouteView RouteData="routeData"
DefaultLayout="typeof(MainLayout)" />
...
</Found>
</Router>
</CascadingAuthenticationState>
注意
隨著 ASP.NET Core 5.0.1 的發行以及在任何其他 5.x 版中,Router
元件會包含設定為 @true
的 PreferExactMatches
參數。 如需詳細資訊,請參閱從 ASP.NET Core 3.1 移轉至 5.0。
在用戶端 Blazor 應用程式中,將授權服務新增至 Program
檔案:
builder.Services.AddAuthorizationCore();
在用戶端 Blazor 應用程式中,將選項和授權服務新增至 Program
檔案:
builder.Services.AddOptions();
builder.Services.AddAuthorizationCore();
在伺服器端 Blazor 應用程式中,選項和授權的服務已經存在,因此不需要再採取進一步動作。
授權
在使用者被驗證之後,系統便會套用「授權」規則以控制使用者可以執行的動作。
存取權通常會依據下列情況來授與或拒絕:
- 使用者已通過驗證 (已登入)。
- 使用者屬於某個「角色」。
- 使用者具有「宣告」。
- 已滿足某個「原則」。
上述概念皆和 ASP.NET Core MVC 或 Razor Pages 應用程式中的概念相同。 如需 ASP.NET Core 安全性的詳細資訊,請參閱 ASP.NET Core 安全性與Identity下的文章。
AuthorizeView
元件
AuthorizeView 元件會根據使用者是否獲得授權來選擇性地顯示 UI 內容。 此方法讓您只需要向使用者顯示資料,不用在程序性邏輯中使用使用者的 identity。
該元件會公開 AuthenticationState 類型的 context
變數 (Razor 語法中的 @context
),您可以使用它來存取已登入使用者的相關資訊:
<AuthorizeView>
<p>Hello, @context.User.Identity?.Name!</p>
</AuthorizeView>
您可以也透過 Authorized 和 NotAuthorized 參數的組合,根據使用者獲得授權與否來提供不同的顯示內容:
<AuthorizeView>
<Authorized>
<p>Hello, @context.User.Identity?.Name!</p>
<p><button @onclick="HandleClick">Authorized Only Button</button></p>
</Authorized>
<NotAuthorized>
<p>You're not authorized.</p>
</NotAuthorized>
</AuthorizeView>
@code {
private void HandleClick() { ... }
}
AuthorizeView雖然元件會根據使用者的授權狀態控制元素的可見度,但它不會對事件處理程式本身強制執行安全性。 在上述範例中, HandleClick
方法只會與授權用戶可見的按鈕相關聯,但沒有任何方法可防止從其他地方叫用此方法。 若要確保方法層級安全性,請在處理程式本身或相關 API 中實作額外的授權邏輯。
Razor 當靜態伺服器端轉譯 (靜態 SSR) 期間授權失敗時,Blazor Web App 的元件一律不會顯示 <NotAuthorized>
內容。 伺服器端 ASP.NET Core 管線會處理伺服器上的授權。 使用伺服器端技術來處理未經授權的要求。 如需詳細資訊,請參閱 ASP.NET Core Blazor 轉譯模式。
警告
與 AuthorizeView 相關聯的用戶端端標記和方法只會受到保護,無法在用戶端端應用程式 Blazor 中 轉譯的 UI 中檢視和執行。 為了保護用戶端端 Blazor 中授權的內容和安全方法,內容通常是由安全、授權的 Web API 呼叫提供給伺服器 API,且永遠不會儲存在應用程式中。 如需詳細資訊,請參閱 從 ASP.NET Core Blazor應用程式 呼叫 Web API 和 ASP.NET CoreBlazor WebAssembly 其他安全性案例。
Authorized 和 NotAuthorized 的內容可以包含任意項目,例如其他互動式元件。
授權情況 (例如控制 UI 選項或存取的角色或原則) 已涵蓋於授權一節。
如果未指定授權條件,AuthorizeView 會使用預設的原則:
- 已驗證 (已登入) 的使用者視為已授權。
- 未驗證 (已登出) 的使用者視為未授權。
AuthorizeView 元件可用於 NavMenu
元件 (Shared/NavMenu.razor
) 以顯示 NavLink
元件 (NavLink),但請注意,此方法只會從轉譯的輸出中移除清單項目。 其無法防止使用者瀏覽至元件。 在目的地元件中個別實作授權。
角色型和原則型授權
AuthorizeView 元件支援「角色型」或「原則型」授權。
針對角色型授權,請使用 Roles 參數。 在下列範例中,使用者必須具有 Admin
或 Superuser
角色的角色宣告:
<AuthorizeView Roles="Admin, Superuser">
<p>You have an 'Admin' or 'Superuser' role claim.</p>
</AuthorizeView>
若要要求使用者同時具有 Admin
和 Superuser
角色宣告,請巢狀 AuthorizeView 元件:
<AuthorizeView Roles="Admin">
<p>User: @context.User</p>
<p>You have the 'Admin' role claim.</p>
<AuthorizeView Roles="Superuser" Context="innerContext">
<p>User: @innerContext.User</p>
<p>You have both 'Admin' and 'Superuser' role claims.</p>
</AuthorizeView>
</AuthorizeView>
上述程式碼會為內部 AuthorizeView 元件建立 Context
,以防止 AuthenticationState 內容衝突。 AuthenticationState 內容會在外部 AuthorizeView 使用存取內容的標準方法 (@context.User
) 存取。 內容會在內部 AuthorizeView 使用具名 innerContext
內容 (@innerContext.User
) 存取。
如需詳細資訊,包括設定指引,請參閱 ASP.NET Core 中的角色型授權。
針對以原則為基礎的授權,請使用 Policy 參數搭配單一原則名稱:
<AuthorizeView Policy="Over21">
<p>You satisfy the 'Over21' policy.</p>
</AuthorizeView>
若要處理使用者應該滿足數個原則之一的情況,請建立原則,確認使用者符合其他原則。
若要處理使用者必須同時滿足數個原則的情況,請採取 下列其中一種 方法:
建立 AuthorizeView 的原則,確認使用者符合數個其他原則。
在多個 AuthorizeView 元件中巢狀原則:
<AuthorizeView Policy="Over21"> <AuthorizeView Policy="LivesInCalifornia"> <p>You satisfy the 'Over21' and 'LivesInCalifornia' policies.</p> </AuthorizeView> </AuthorizeView>
宣告型授權是特殊案例的原則型授權。 例如,您可以定義要求使用者具備特定宣告的原則。 如需詳細資訊,請參閱 ASP.NET Core 中的原則型授權。
如果未指定 Roles 和 Policy,AuthorizeView 便會使用預設原則:
- 已驗證 (已登入) 的使用者視為已授權。
- 未驗證 (已登出) 的使用者視為未授權。
因為 .NET 字串比較會區分大小寫,所以比對角色與原則名稱也會區分大小寫。 例如,Admin
(大寫 A
) 不會被視為與 admin
(小寫 a
) 相同的角色。
Pascal 大小寫通常用於角色和原則名稱 (例如 BillingAdministrator
),但使用 Pascal 大小寫並非嚴格的需求。 允許不同的大小寫方案,如駝峰式大小寫、肉串式大小寫和蛇式大小寫。 在角色和原則名稱中使用空格不尋常,但架構允許。 例如,billing administrator
在 .NET 應用程式中雖是不尋常的角色或原則名稱格式,但是個有效的角色或原則名稱。
在非同步驗證期間所顯示的內容
Blazor 允許以「非同步」方式判斷驗證狀態。 此方法的主要案例是會向外部端點要求驗證的用戶端端 Blazor 應用程式。
在進行驗證期間,AuthorizeView 不會顯示任何內容。 若要在驗證進行時顯示內容,請將內容指派給 Authorizing 參數:
<AuthorizeView>
<Authorized>
<p>Hello, @context.User.Identity?.Name!</p>
</Authorized>
<Authorizing>
<p>You can only see this content while authentication is in progress.</p>
</Authorizing>
</AuthorizeView>
此方法通常不適用於伺服器端 Blazor 應用程式。 伺服器端 Blazor 應用程式在驗證狀態建立時,便能立即得知該狀態。 可以在應用程式的 AuthorizeView 元件中提供 Authorizing 內容,但該內容永遠不會顯示。
[Authorize]
屬性
可在 Razor 元件中使用[Authorize]
屬性:
@page "/"
@attribute [Authorize]
You can only see this if you're signed in.
重要
請僅在透過 Blazor 路由器抵達的 @page
元件上使用 [Authorize]
。 授權僅會以路由的層面執行,且「不」適用於在頁面內轉譯的子元件。 若要授權在頁面內顯示特定組件,請改為使用 AuthorizeView。
[Authorize]
屬性也支援角色型或原則型授權。 針對角色型授權,請使用 Roles 參數:
@page "/"
@attribute [Authorize(Roles = "Admin, Superuser")]
<p>You can only see this if you're in the 'Admin' or 'Superuser' role.</p>
針對原則型授權,請使用 Policy 參數:
@page "/"
@attribute [Authorize(Policy = "Over21")]
<p>You can only see this if you satisfy the 'Over21' policy.</p>
如果未指定 Roles 和 Policy,[Authorize]
便會使用預設原則:
- 已驗證 (已登入) 的使用者視為已授權。
- 未驗證 (已登出) 的使用者視為未授權。
當使用者未獲得授權,且應用程式未 使用 Router
元件自訂未經授權的內容時,架構會自動顯示下列後援訊息:
Not authorized.
資源授權
若要授權使用者使用資源,請將要求的路由資料傳遞至 AuthorizeRouteView 的 Resource 參數。
在要求路由的 Router.Found 內容中:
<AuthorizeRouteView Resource="routeData" RouteData="routeData"
DefaultLayout="typeof(MainLayout)" />
如需如何在程序邏輯中傳遞及使用授權狀態資料的詳細資訊,請參閱將驗證狀態公開為串聯參數一節。
當 AuthorizeRouteView 收到資源的路由資料時,授權原則可以存取 RouteData.PageType 和 RouteData.RouteValues 以讓自訂邏輯決定是否授權。
下列範例會使用下列邏輯,在 AuthorizationOptions 中為應用程式的授權服務設定 (AddAuthorizationCore) 建立 EditUser
原則:
- 判斷是否有索引鍵為
id
的路由值存在。 如果該索引鍵存在,路由值便會儲存到value
中。 - 在名為
id
的變數中,將value
儲存為字串,或設定空字串值 (string.Empty
)。 - 如果
id
不是空字串,且字串值的開頭為EMP
,則判定滿足原則 (傳回true
)。 否則,判定原則失敗 (傳回false
)。
在 Program
檔案中:
為 Microsoft.AspNetCore.Components 和 System.Linq 新增命名空間:
using Microsoft.AspNetCore.Components; using System.Linq;
新增原則:
options.AddPolicy("EditUser", policy => policy.RequireAssertion(context => { if (context.Resource is RouteData rd) { var routeValue = rd.RouteValues.TryGetValue("id", out var value); var id = Convert.ToString(value, System.Globalization.CultureInfo.InvariantCulture) ?? string.Empty; if (!string.IsNullOrEmpty(id)) { return id.StartsWith("EMP", StringComparison.InvariantCulture); } } return false; }) );
上述範例是過度簡化的授權原則,這麼做只是為了透過運作範例來示範概念。 如需如何建立和設定授權原則的詳細資訊,請參閱 ASP.NET Core 中的原則型授權。
在下列 EditUser
元件中,位於 /users/{id}/edit
的資源具有使用者識別碼 ({id}
) 的路由參數。 元件會使用上述 EditUser
授權原則來判斷 id
的路由值是否以 EMP
開頭。 如果 id
以 EMP
開頭,則原則會成功,且會獲得授權而能夠存取元件。 如果 id
以 EMP
以外的值開頭,或如果 id
是空字串,則原則會失敗,且元件不會載入。
EditUser.razor
:
@page "/users/{id}/edit"
@using Microsoft.AspNetCore.Authorization
@attribute [Authorize(Policy = "EditUser")]
<h1>Edit User</h1>
<p>The "EditUser" policy is satisfied! <code>Id</code> starts with 'EMP'.</p>
@code {
[Parameter]
public string? Id { get; set; }
}
@page "/users/{id}/edit"
@using Microsoft.AspNetCore.Authorization
@attribute [Authorize(Policy = "EditUser")]
<h1>Edit User</h1>
<p>The "EditUser" policy is satisfied! <code>Id</code> starts with 'EMP'.</p>
@code {
[Parameter]
public string? Id { get; set; }
}
使用 Router
元件來自訂未經授權的內容
如有下列情況,Router 元件與 AuthorizeRouteView 元件可讓應用程式指定自訂內容:
- 使用者無法滿足套用至元件的
[Authorize]
條件。 系統會顯示<NotAuthorized>
元素的標記。[Authorize]
屬性一節會說明[Authorize]
屬性。 - 正在進行非同步授權,這通常表示正在進行驗證使用者的程序。 系統會顯示
<Authorizing>
元素的標記。
重要
顯示 <NotAuthorized>
和 <NotFound>
內容的 Blazor 路由器功能無法在靜態伺服器端轉譯 (靜態 SSR) 期間運作,因為要求處理完全由 ASP.NET Core 中介軟體管線要求處理,且 Razor 元件針對未經授權的或不正確的要求完全不會轉譯。 使用伺服器端技術來處理靜態 SSR 期間未經授權的和不正確的要求。 如需詳細資訊,請參閱 ASP.NET Core Blazor 轉譯模式。
<Router ...>
<Found ...>
<AuthorizeRouteView ...>
<NotAuthorized>
...
</NotAuthorized>
<Authorizing>
...
</Authorizing>
</AuthorizeRouteView>
</Found>
</Router>
Authorized 和 NotAuthorized 的內容可以包含任意項目,例如其他互動式元件。
注意
上述內容要求在應用程式的 Program
檔案中註冊串聯驗證狀態服務:
builder.Services.AddCascadingAuthenticationState();
<CascadingAuthenticationState>
<Router ...>
<Found ...>
<AuthorizeRouteView ...>
<NotAuthorized>
...
</NotAuthorized>
<Authorizing>
...
</Authorizing>
</AuthorizeRouteView>
</Found>
</Router>
</CascadingAuthenticationState>
NotFound、Authorized 及 NotAuthorized 的內容可以包含任意項目,例如其他互動式元件。
如果未指定 NotAuthorized 內容,AuthorizeRouteView 會使用下列後援訊息:
Not authorized.
從已啟用驗證的 Blazor WebAssembly 專案範本建立的應用程式會包含位於 Router 元件 <NotAuthorized>
內容中的 RedirectToLogin
元件。 未驗證使用者時 (context.User.Identity?.IsAuthenticated != true
),RedirectToLogin
元件會將瀏覽器重新導向至 authentication/login
端點以進行驗證。 使用者會在向 identity 提供者進行驗證之後,傳回至要求的網址。
程序性邏輯
如果作為程序性邏輯的一部分,應用程式必須檢查授權規則,請使用 Task<
AuthenticationState>
類型的階層式參數來取得使用者的 ClaimsPrincipal。 Task<
AuthenticationState>
可以與其他服務 (例如 IAuthorizationService
) 結合來評估原則。
在以下範例中:
user.Identity.IsAuthenticated
會針對已驗證 (已登入) 的使用者執行程式碼。user.IsInRole("admin")
會針對 「管理員」角色中的使用者執行程式碼。(await AuthorizationService.AuthorizeAsync(user, "content-editor")).Succeeded
會針對滿足「內容編輯器」原則的使用者執行程式碼。
從專案範本建立時,伺服器端 Blazor 應用程式會包含適當的命名空間。 在用戶端端 Blazor 應用程式中,確認元件或應用程式的 _Imports.razor
檔案中是否存在 Microsoft.AspNetCore.Authorization 和 Microsoft.AspNetCore.Components.Authorization 命名空間:
@using Microsoft.AspNetCore.Authorization
@using Microsoft.AspNetCore.Components.Authorization
ProceduralLogic.razor
:
@page "/procedural-logic"
@inject IAuthorizationService AuthorizationService
<h1>Procedural Logic Example</h1>
<button @onclick="@DoSomething">Do something important</button>
@code {
[CascadingParameter]
private Task<AuthenticationState>? authenticationState { get; set; }
private async Task DoSomething()
{
if (authenticationState is not null)
{
var authState = await authenticationState;
var user = authState?.User;
if (user is not null)
{
if (user.Identity is not null && user.Identity.IsAuthenticated)
{
// ...
}
if (user.IsInRole("Admin"))
{
// ...
}
if ((await AuthorizationService.AuthorizeAsync(user, "content-editor"))
.Succeeded)
{
// ...
}
}
}
}
}
@page "/procedural-logic"
@inject IAuthorizationService AuthorizationService
<h1>Procedural Logic Example</h1>
<button @onclick="@DoSomething">Do something important</button>
@code {
[CascadingParameter]
private Task<AuthenticationState>? authenticationState { get; set; }
private async Task DoSomething()
{
if (authenticationState is not null)
{
var authState = await authenticationState;
var user = authState?.User;
if (user is not null)
{
if (user.Identity is not null && user.Identity.IsAuthenticated)
{
// ...
}
if (user.IsInRole("Admin"))
{
// ...
}
if ((await AuthorizationService.AuthorizeAsync(user, "content-editor"))
.Succeeded)
{
// ...
}
}
}
}
}
針對錯誤進行疑難排解
常見錯誤:
授權需要
Task<AuthenticationState>
類型的串聯參數。 請考慮使用CascadingAuthenticationState
來進行提供。針對
authenticationStateTask
接收到null
值
專案很可能不是使用已啟用驗證的伺服器端 Blazor 範本建立。
在 .NET 7 或更早版本中,請將 <CascadingAuthenticationState>
圍繞 UI 樹狀結構的某些部分,例如圍繞 Blazor 路由器:
<CascadingAuthenticationState>
<Router ...>
...
</Router>
</CascadingAuthenticationState>
在 .NET 8 或更新版本中,請勿使用 CascadingAuthenticationState 元件:
- <CascadingAuthenticationState>
<Router ...>
...
</Router>
- </CascadingAuthenticationState>
作為替代,請將串聯驗證狀態服務新增至 Program
檔案中的服務集合:
builder.Services.AddCascadingAuthenticationState();
AddCascadingAuthenticationState (.NET 8 或更新版本) 所提供的 CascadingAuthenticationState 元件 (.NET 7 或更早版本) 或服務可支援 AuthenticationState>
Task<
串聯參數,使其接收基礎 AuthenticationStateProvider 相依性插入服務。
個人識別資訊 (PII)
當文件涉及個人標識資訊 (PII) 時,Microsoft 是採用 GDPR 對「個人資料」的定義 (GDPR 4.1)。
PII 是指已識別或可識別自然人的任何相關資訊。 可識別的自然人是指可透過下列任一項內容,直接或間接識別的人員:
- 名稱
- 身分證號碼
- 位置座標
- 連線識別碼
- 其他特定因素
- 實體
- 生理
- 遺傳
- 精神 (心理)
- 經濟
- 文化
- 社交 identity
其他資源
- 伺服器端和資源Blazor Web App
- 快速入門:透過 Microsoft 將登入新增至 ASP.NET Core Web 應用程式
- 快速入門:使用 Microsoft identity 平台來保護 ASP.NET Core Web API
- 設定 ASP.NET Core 以與 Proxy 伺服器和負載平衡器搭配運作:包含下列指引:
- 使用轉送的標頭中介軟體來跨 Proxy 伺服器和內部網路保留 HTTPS 配置資訊。
- 其他案例和使用案例,包括手動配置設定、正確要求路由的要求路徑變更,以及轉送 Linux 和非 IIS 反向 Proxy 的要求配置。
- Microsoft identity 平台文件
- ASP.NET Core 安全性主題
- 在 ASP.NET Core 中設定 Windows 驗證
- 建置 Authentication.MSAL JavaScript 程式庫的自訂版本
- 有趣的 Blazor:驗證 社群範例連結
- ASP.NET Core Blazor Hybrid 驗證與授權
- 伺服器端 Blazor 資源
- 快速入門:透過 Microsoft 將登入新增至 ASP.NET Core Web 應用程式
- 快速入門:使用 Microsoft identity 平台來保護 ASP.NET Core Web API
- 設定 ASP.NET Core 以與 Proxy 伺服器和負載平衡器搭配運作:包含下列指引:
- 使用轉送的標頭中介軟體來跨 Proxy 伺服器和內部網路保留 HTTPS 配置資訊。
- 其他案例和使用案例,包括手動配置設定、正確要求路由的要求路徑變更,以及轉送 Linux 和非 IIS 反向 Proxy 的要求配置。
- Microsoft identity 平台文件
- ASP.NET Core 安全性主題
- 在 ASP.NET Core 中設定 Windows 驗證
- 建置 Authentication.MSAL JavaScript 程式庫的自訂版本
- 有趣的 Blazor:驗證 社群範例連結