本文說明如何使用範例應用程式,透過 Microsoft Blazor Web App與 來結合 Identity,以保護 。
本文的此版本涵蓋在不採用 前端後端模式的情況下實作 Entra。 BFF 模式適用於對外部服務提出已驗證的要求。 如果應用程式的規格要求採用 BFF 模式,請將發行項版本選取器變更為 BFF 模式。
涵蓋下列規格:
-
Blazor Web App 使用自動渲染模式搭配全域互動性(
InteractiveAuto)。 - 伺服器專案會呼叫 AddAuthenticationStateSerialization,以新增伺服器端驗證狀態提供者,用來透過 PersistentComponentState 將驗證狀態傳遞至用戶端。 用戶端會呼叫 AddAuthenticationStateDeserialization 來反序列化並使用伺服器傳遞的驗證狀態。 該驗證狀態在 WebAssembly 應用程式的存留期內是固定的。
- 應用程式使用以
Microsoft 套件為基礎的網頁 Microsoft Entra ID 。 - 架構會管理自動的非互動式令牌更新。
- 應用程式會使用伺服器端和客戶端服務抽象概念來顯示產生的天氣資料:
- 在伺服器上渲染
Weather元件來顯示天氣資料時,此元件會使用ServerWeatherForecaster。 Microsoft Identity Web 套件提供 API,以建立具名下游 Web 服務以進行 Web API 呼叫。 IDownstreamApi 會插入 至ServerWeatherForecaster,用來呼叫 CallApiForUserAsync 以從外部 Web API (MinimalApiJwt專案) 取得天氣數據。 - 當元件
Weather在用戶端上渲染時,該元件會使用ClientWeatherForecaster服務實作,而該實作會使用預先設定的HttpClient,這個設定位於用戶端專案的Program檔案中,以對伺服器專案的最小 API(/weather-forecast)發起 Web API 呼叫,以獲取天氣數據。 最小 API 端點會從ServerWeatherForecaster類別取得天氣數據,並將它傳回給用戶端,以供元件轉譯。
- 在伺服器上渲染
範例解決方案
範例解決方案包含下列專案:
-
BlazorWebAppEntra: Blazor Web App的伺服器端專案,包含天氣資料的 最小 API 端點範例。 -
BlazorWebAppEntra.Client: Blazor Web App的用戶端專案。 -
MinimalApiJwt:後端 Web API,包含天氣資料的最小 API 端點範例。
使用下列連結,透過 Blazor 範例存放庫中的最新版本資料夾存取範例。 此範例位於 .NET 9 或更新版本的 BlazorWebAppEntra 資料夾中。
從 Aspire/Aspire.AppHost 項目 啟動解決方案。
檢視或下載範例程式碼 \(英文\) (如何下載)
Microsoft Entra ID 應用程式註冊
我們建議針對應用程式和 Web API 使用不同的註冊,即使應用程式和 Web API 位於相同的解決方案中也一樣。 下列指引適用於 BlazorWebAppEntra 範例解決方案的應用程式和 MinimalApiJwt Web API,但相同的指導方針通常適用於應用程式和 Web API 的任何以 Entra 為基礎的註冊。
先註冊 Web API (MinimalApiJwt),讓您可以在註冊應用程式時授與 Web API 的存取權。 Web API 的租用戶標識碼和用戶端識別碼可用來在其 Program 檔案中設定 Web API。 註冊 Web API 之後,請在應用程式註冊>中公開 WebAPI 公開具有 範圍名稱的 Weather.GetAPI。 記錄應用程式識別碼 URI 以用於應用程式的組態。
接著,將應用程式BlazorWebAppEntra註冊為Web 平台設定,並在 Redirect URI:https://localhost/signin-oidc 和 https://localhost/signout-callback-oidc (這些 URI 不需要指定埠口)。 將 前通道登出網址 設為 https://localhost/signout-callback-oidc (不需要埠號)。 應用程式的租使用者標識碼、租使用者網域和用戶端識別碼,以及 Web API 的基地址、應用程式識別碼 URI 和天氣範圍名稱,可用來在其 appsettings.json 檔案中設定應用程式。 授與 API 許可權,以存取 應用程式註冊>API 許可權中的 Web API。 如果應用程式的安全性規格要求它,您可以授與系統管理員同意,讓組織存取 Web API。 授權的使用者和群組會指派給應用程式註冊>的應用程式註冊。
在 Entra 或 Azure 入口網站的 隱含授與和混合式流程 應用程式註冊設定中,請勿選取授權端點的複選框以傳回 存取令牌 或 標識碼令牌。 OpenID Connect 處理程式會使用從授權端點傳回的程式代碼,自動要求適當的令牌。
在 Entra 或 Azure 入口網站的應用程式註冊中建立客戶端密碼(管理>憑證和秘密>新客戶端密碼)。 請保留用戶端秘密 值 ,以使用下一節。
本文稍後會提供特定設定的其他 Entra 設定指引。
伺服器端 Blazor Web App 專案 (BlazorWebAppEntra)
BlazorWebAppEntra 專案是 Blazor Web App的伺服器端專案。
Blazor Web App 用戶端專案 (BlazorWebAppEntra.Client)
BlazorWebAppEntra.Client 專案是 Blazor Web App的用戶端專案。
如果使用者需要在用戶端轉譯期間登入或註銷,則會起始完整頁面重載。
後端 Web API 專案 (MinimalApiJwt)
MinimalApiJwt 專案是多個前端專案的後端 Web API。 專案會為天氣資料設定最小 API 端點。
MinimalApiJwt.http 檔案可用於測試天氣資料要求。 請注意,MinimalApiJwt 專案必須執行才能測試端點,而且端點會硬式編碼到檔案中。 如需詳細資訊,請參閱在 Visual Studio 2022 中使用 .http 檔案。
專案包含用來產生 OpenAPI 檔的套件和配置。
安全的氣象預報數據端點位於專案的 Program 檔案中:
app.MapGet("/weather-forecast", () =>
{
var forecast = Enumerable.Range(1, 5).Select(index =>
new WeatherForecast
(
DateOnly.FromDateTime(DateTime.Now.AddDays(index)),
Random.Shared.Next(-20, 55),
summaries[Random.Shared.Next(summaries.Length)]
))
.ToArray();
return forecast;
}).RequireAuthorization();
RequireAuthorization 擴充方法需要路由定義的授權。 針對您新增至專案的任何控制器,請將 [Authorize] 屬性 新增至控制器或動作。
設定後端 Web API 專案 (MinimalApiJwt)
在JwtBearerOptionsAddJwtBearer專案的MinimalApiJwt檔案中設定Program。
針對 Web API 應用程式的註冊,Weather.Get 範圍是在 Entra 或 Azure 入口網站的 Expose an API 中設定。
Authority 設定 OIDC 呼叫的權限。
jwtOptions.Authority = "{AUTHORITY}";
以下範例使用租戶 ID 為 , aaaabbbb-0000-cccc-1111-dddd2222eeee 目錄名稱為 contoso。
如果應用程式已在 ME-ID 承租者中註冊,授權機構應與識別提供者所返回的 JWT 的發行者(iss)匹配。
jwtOptions.Authority = "https://sts.windows.net/aaaabbbb-0000-cccc-1111-dddd2222eeee";
如果該應用程式註冊於 Microsoft Entra 外部 ID 租戶中:
jwtOptions.Authority = "https://contoso.ciamlogin.com/aaaabbbb-0000-cccc-1111-dddd2222eeee/v2.0";
如果應用程式已在 AAD B2C 租用戶中註冊:
jwtOptions.Authority = "https://login.microsoftonline.com/aaaabbbb-0000-cccc-1111-dddd2222eeee/v2.0";
Note
自 2025 年 5 月 1 日起,Azure Active Directory B2C 不再提供給新客戶提供服務。 AAD B2C 租戶適用於 2025 年 5 月 1 日前建立帳戶的客戶,至 2030 年皆可使用。 欲了解更多資訊,請參閱 Azure AD B2C:常見問題(FAQ)。
Audience 會為任何已接收的 JWT 存取令牌設定對象。
jwtOptions.Audience = "{AUDIENCE}";
在 Entra 或 Azure 入口網站中,將值與在 [公開 API] 下新增 Weather.Get 範疇時所配置的 應用程式識別碼 URI 的路徑相符。 請勿在值中包含範圍名稱 "Weather.Get"。
下列範例使用的應用程式 (用戶端) 識別碼 11112222-bbbb-3333-cccc-4444dddd5555。 第三個例子使用了 contoso.onmicrosoft.com 的租戶域。
ME-ID 租使用者範例:
jwtOptions.Audience = "api://11112222-bbbb-3333-cccc-4444dddd5555";
Microsoft Entra 外部 ID 租戶:
jwtOptions.Audience = "11112222-bbbb-3333-cccc-4444dddd5555";
AAD B2C 租使用者範例:
jwtOptions.Audience = "https://contoso.onmicrosoft.com/11112222-bbbb-3333-cccc-4444dddd5555";
設定伺服器專案 (BlazorWebAppEntra)
AddMicrosoftIdentityWebApp從 Microsoft Identity Web (Microsoft.Identity.WebNuGet 套件、API 文件)設定在專案的BlazorWebAppEntra檔案中。
從 Entra 或 Azure 入口網站中的應用程式註冊,取得應用程式(用戶端)識別碼、租戶(出版本)網域和目錄(租戶)識別碼。 應用程式識別碼 URI 是從 Web API 的Weather.Get註冊中取得的作用域。 從入口網站取得應用程式識別碼 URI 時,請勿包含範圍名稱。
認證設定依租戶類型而異:
ME-ID 租戶配置
此條款適用於註冊於 Microsoft Entra ID 或 Azure AAD B2C 租戶的應用程式。
在 BlazorWebAppEntra 項目的 Program 檔案中,提供以下 Microsoft Identity Web 組態中的佔位符值:
builder.Services.AddAuthentication(OpenIdConnectDefaults.AuthenticationScheme)
.AddMicrosoftIdentityWebApp(msIdentityOptions =>
{
msIdentityOptions.CallbackPath = "/signin-oidc";
msIdentityOptions.ClientId = "{CLIENT ID (BLAZOR APP)}";
msIdentityOptions.Domain = "{DIRECTORY NAME}.onmicrosoft.com";
msIdentityOptions.Instance = "https://login.microsoftonline.com/";
msIdentityOptions.ResponseType = "code";
msIdentityOptions.TenantId = "{TENANT ID}";
})
.EnableTokenAcquisitionToCallDownstreamApi()
.AddDownstreamApi("DownstreamApi", configOptions =>
{
configOptions.BaseUrl = "{BASE ADDRESS}";
configOptions.Scopes = ["{APP ID URI}/Weather.Get"];
})
.AddDistributedTokenCaches();
上述設定中的占位符:
-
{CLIENT ID (BLAZOR APP)}:應用程式 (用戶端) 識別碼。 -
{DIRECTORY NAME}:租戶(發佈者)網域的目錄名稱。 -
{TENANT ID}:目錄(租用戶)識別碼。 -
{BASE ADDRESS}:Web API 的基位址。 -
{APP ID URI}:Web API 範圍的應用程式識別碼 URI。 下列格式之一會被使用,其中{CLIENT ID (WEB API)}佔位元是 Web API 的 Entra 註冊的用戶端識別碼,而{DIRECTORY NAME}佔位元是承租者(發行者)網域的目錄名稱(例如:contoso)。- ME-ID 租戶格式:
api://{CLIENT ID (WEB API)} - B2C 租戶格式:
https://{DIRECTORY NAME}.onmicrosoft.com/{CLIENT ID (WEB API)}
- ME-ID 租戶格式:
Example:
builder.Services.AddAuthentication(OpenIdConnectDefaults.AuthenticationScheme)
.AddMicrosoftIdentityWebApp(msIdentityOptions =>
{
msIdentityOptions.CallbackPath = "/signin-oidc";
msIdentityOptions.ClientId = "00001111-aaaa-2222-bbbb-3333cccc4444";
msIdentityOptions.Domain = "contoso.onmicrosoft.com";
msIdentityOptions.Instance = "https://login.microsoftonline.com/";
msIdentityOptions.ResponseType = "code";
msIdentityOptions.TenantId = "aaaabbbb-0000-cccc-1111-dddd2222eeee";
})
.EnableTokenAcquisitionToCallDownstreamApi()
.AddDownstreamApi("DownstreamApi", configOptions =>
{
configOptions.BaseUrl = "https://localhost:7277";
configOptions.Scopes = ["api://11112222-bbbb-3333-cccc-4444dddd5555/Weather.Get"];
})
.AddDistributedTokenCaches();
Microsoft Entra 外部 ID 配置
本節適用於註冊於 Microsoft Entra 外部 ID 租戶的應用程式。
在 BlazorWebAppEntra 項目的 Program 檔案中,提供以下 Microsoft Identity Web 組態中的佔位符值:
builder.Services.AddAuthentication(OpenIdConnectDefaults.AuthenticationScheme)
.AddMicrosoftIdentityWebApp(msIdentityOptions =>
{
msIdentityOptions.CallbackPath = "/signin-oidc";
msIdentityOptions.Authority = "https://{DIRECTORY NAME}.ciamlogin.com/{TENANT ID}/v2.0";
msIdentityOptions.ClientId = "{CLIENT ID (BLAZOR APP)}";
msIdentityOptions.ResponseType = "code";
})
.EnableTokenAcquisitionToCallDownstreamApi()
.AddDownstreamApi("DownstreamApi", configOptions =>
{
configOptions.BaseUrl = "{BASE ADDRESS}";
configOptions.Scopes = ["{APP ID URI}/Weather.Get"];
})
.AddDistributedTokenCaches();
上述設定中的占位符:
-
{DIRECTORY NAME}:租戶(發佈者)網域的目錄名稱。 -
{CLIENT ID (BLAZOR APP)}:應用程式 (用戶端) 識別碼。 -
{BASE ADDRESS}:Web API 的基位址。 -
{APP ID URI}:Web API 範圍的應用程式識別碼 URI。 以下兩種格式皆可使用,{CLIENT ID (WEB API)}其中佔位符為網頁 API Entra 註冊的用戶端 ID,{DIRECTORY NAME}佔位符為租戶(發布者)網域的目錄名稱(例如:contoso)。- ME-ID 或 Microsoft Entra 外部 ID 租戶格式:
api://{CLIENT ID (WEB API)} - B2C 租戶格式:
https://{DIRECTORY NAME}.onmicrosoft.com/{CLIENT ID (WEB API)}
- ME-ID 或 Microsoft Entra 外部 ID 租戶格式:
Example:
builder.Services.AddAuthentication(OpenIdConnectDefaults.AuthenticationScheme)
.AddMicrosoftIdentityWebApp(msIdentityOptions =>
{
msIdentityOptions.CallbackPath = "/signin-oidc";
msIdentityOptions.Authority = "https://contoso.ciamlogin.com/aaaabbbb-0000-cccc-1111-dddd2222eeee/v2.0";
msIdentityOptions.ClientId = "00001111-aaaa-2222-bbbb-3333cccc4444";
msIdentityOptions.ResponseType = "code";
})
.EnableTokenAcquisitionToCallDownstreamApi()
.AddDownstreamApi("DownstreamApi", configOptions =>
{
configOptions.BaseUrl = "https://localhost:7277";
configOptions.Scopes = ["api://11112222-bbbb-3333-cccc-4444dddd5555/Weather.Get"];
})
.AddDistributedTokenCaches();
回呼路徑 (CallbackPath) 必須符合在 Entra 或 Azure 入口網站 中註冊應用程式時所設定的重新導向 URI(登入回呼路徑)。 應用程式註冊的 驗證 設定頁面中設定路徑。 預設值 CallbackPath 為 /signin-oidc、註冊的重新導向 URI https://localhost/signin-oidc (不需要埠)。
SignedOutCallbackPath是使用者代理程式從Entra登出後,OpenID Connect處理程式在應用程式基底路徑內攔截的要求路徑。 範例應用程式不會設定路徑的值,因為會使用預設值 「/signout-callback-oidc」。。 攔截要求之後,如果指定,OpenID Connect 處理程式會重新導向至 SignedOutRedirectUri 或 RedirectUri。
Warning
請勿在用戶端程式代碼中儲存應用程式密碼、連接字串、認證、密碼、個人標識元(PIN)、私人 C#/.NET 程式代碼或私鑰/令牌,這一律不安全。 在測試/預備和生產環境中,伺服器端 Blazor 程序代碼和 Web API 應該使用安全驗證流程,以避免在專案程式代碼或組態檔內維護認證。 在本機開發測試之外,建議您避免使用環境變數來儲存敏感數據,因為環境變數不是最安全的方法。 針對本機開發測試, 建議使用秘密管理員工具 來保護敏感數據。 如需詳細資訊,請參閱 安全地維護敏感數據和認證。
本文的這個版本涵蓋如何利用 Backend for Frontend (BFF) 模式實作 Entra。 如果應用程式規格不要求採用 BFF 模式,請將發行項版本選取器變更為 非 BFF 模式。
涵蓋下列規格:
-
Blazor Web App 使用自動渲染模式搭配全域互動性(
InteractiveAuto)。 - 伺服器專案會呼叫 AddAuthenticationStateSerialization,以新增伺服器端驗證狀態提供者,用來透過 PersistentComponentState 將驗證狀態傳遞至用戶端。 用戶端會呼叫 AddAuthenticationStateDeserialization 來反序列化並使用伺服器傳遞的驗證狀態。 該驗證狀態在 WebAssembly 應用程式的存留期內是固定的。
- 應用程式使用以
Microsoft 套件為基礎的網頁 Microsoft Entra ID 。 - 架構會管理自動的非互動式令牌更新。
- 採用前端的後端 (BFF) 模式,使用 Aspire 進行服務探索,並使用 YARP 將請求代理到後端應用程式的天氣預報端點。
- 後端 Web API 使用 JWT 持有者驗證來驗證登入 Blazor Web App中 cookie 所儲存的 JWT 權杖。
- Aspire 改善建置 .NET 雲端原生應用程式的體驗。 它提供一組一致固定的工具和模式,用於建置和執行分散式應用程式。
- YARP (又一個反向 Proxy) 是用來建立反向 Proxy 伺服器的程式庫。
- 應用程式會使用伺服器端和客戶端服務抽象概念來顯示產生的天氣數據。
- 在伺服器上渲染
Weather元件來顯示天氣資料時,此元件會使用ServerWeatherForecaster。 Microsoft Identity Web 套件提供 API,以建立具名下游 Web 服務以進行 Web API 呼叫。 IDownstreamApi 會插入 至ServerWeatherForecaster,用來呼叫 CallApiForUserAsync 以從外部 Web API (MinimalApiJwt專案) 取得天氣數據。 - 當元件
Weather在用戶端上渲染時,該元件會使用ClientWeatherForecaster服務實作,而該實作會使用預先設定的HttpClient,這個設定位於用戶端專案的Program檔案中,以對伺服器專案的最小 API(/weather-forecast)發起 Web API 呼叫,以獲取天氣數據。 最小 API 端點會藉由呼叫 GetAccessTokenForUserAsync來取得使用者的存取令牌。 與正確的範圍一起,反向代理呼叫外部 Web API(MinimalApiJwt專案)以取得天氣數據並傳回用戶端,以供元件渲染。
- 在伺服器上渲染
Prerequisites
Aspire 需要 Visual Studio 17.10 版或更新版本。
此外,請參閱的Aspire一節。
範例解決方案
範例解決方案包含下列專案:
-
Aspire:
-
Aspire.AppHost:用來管理應用程式的高階協作事務。 -
Aspire.ServiceDefaults:包含預設的 Aspire 應用程式設定,該設定可視需要加以擴充及自訂。
-
-
MinimalApiJwt:後端 Web API,包含天氣資料的最小 API 端點範例。 -
BlazorWebAppEntra: Blazor Web App的伺服器端專案。 -
BlazorWebAppEntra.Client: Blazor Web App的用戶端專案。
使用下列連結,透過 Blazor 範例存放庫中的最新版本資料夾存取範例。 此範例位於 .NET 9 或更新版本的 BlazorWebAppEntraBff 資料夾中。
檢視或下載範例程式碼 \(英文\) (如何下載)
Microsoft Entra ID 應用程式註冊
我們建議針對應用程式和 Web API 使用不同的註冊,即使應用程式和 Web API 位於相同的解決方案中也一樣。 下列指引適用於 BlazorWebAppEntra 範例解決方案的應用程式和 MinimalApiJwt Web API,但相同的指導方針通常適用於應用程式和 Web API 的任何以 Entra 為基礎的註冊。
先註冊 Web API (MinimalApiJwt),讓您可以在註冊應用程式時授與 Web API 的存取權。 Web API 的租用戶標識碼和用戶端識別碼可用來在其 Program 檔案中設定 Web API。 註冊 Web API 之後,請在應用程式註冊>中公開 WebAPI 公開具有 範圍名稱的 Weather.GetAPI。 記錄應用程式識別碼 URI 以用於應用程式的組態。
接著,將應用程式BlazorWebAppEntra註冊為Web 平台設定,並在 Redirect URI:https://localhost/signin-oidc 和 https://localhost/signout-callback-oidc (這些 URI 不需要指定埠口)。 應用程式的租使用者標識碼、租使用者網域和用戶端識別碼,以及 Web API 的基地址、應用程式識別碼 URI 和天氣範圍名稱,可用來在其 appsettings.json 檔案中設定應用程式。 授與 API 許可權,以存取 應用程式註冊>API 許可權中的 Web API。 如果應用程式的安全性規格要求它,您可以授與系統管理員同意,讓組織存取 Web API。 授權的使用者和群組會指派給應用程式註冊>的應用程式註冊。
在 Entra 或 Azure 入口網站的 隱含授與和混合式流程 應用程式註冊設定中,請勿選取授權端點的複選框以傳回 存取令牌 或 標識碼令牌。 OpenID Connect 處理程式會使用從授權端點傳回的程式代碼,自動要求適當的令牌。
在 Entra 或 Azure 入口網站的應用程式註冊中建立客戶端密碼(管理>憑證和秘密>新客戶端密碼)。 請保留用戶端秘密 值 ,以使用下一節。
本文稍後會提供特定設定的其他 Entra 設定指引。
Aspire 專案
如需有關使用 Aspire 的詳細資訊,以及應用程式範例 .AppHost 和 .ServiceDefaults 專案的詳細資料,請參閱 Aspire 文件。
確認您已符合 Aspire 的必要條件。 如需詳細資訊,請參閱的Aspire一節。
範例應用程式只會設定不安全的 HTTP 啟動設定檔 (http),以在開發測試期間使用。 如需詳細資訊,包括不安全且安全的啟動設定設定檔範例,請參閱允許 Aspire 中不安全的傳輸(Aspire 文件)。
伺服器端 Blazor Web App 專案 (BlazorWebAppEntra)
BlazorWebAppEntra 專案是 Blazor Web App的伺服器端專案。
Blazor Web App 用戶端專案 (BlazorWebAppEntra.Client)
BlazorWebAppEntra.Client 專案是 Blazor Web App的用戶端專案。
如果使用者需要在用戶端轉譯期間登入或註銷,則會起始完整頁面重載。
後端 Web API 專案 (MinimalApiJwt)
MinimalApiJwt 專案是多個前端專案的後端 Web API。 專案會為天氣資料設定最小 API 端點。 來自 Blazor Web App 伺服器端專案 (BlazorWebAppEntra) 的要求會通過 Proxy 處理至 MinimalApiJwt 專案。
MinimalApiJwt.http 檔案可用於測試天氣資料要求。 請注意,MinimalApiJwt 專案必須執行才能測試端點,而且端點會硬式編碼到檔案中。 如需詳細資訊,請參閱在 Visual Studio 2022 中使用 .http 檔案。
專案包含用來產生 OpenAPI 檔的套件和配置。
安全的氣象預報數據端點位於專案的 Program 檔案中:
app.MapGet("/weather-forecast", () =>
{
var forecast = Enumerable.Range(1, 5).Select(index =>
new WeatherForecast
(
DateOnly.FromDateTime(DateTime.Now.AddDays(index)),
Random.Shared.Next(-20, 55),
summaries[Random.Shared.Next(summaries.Length)]
))
.ToArray();
return forecast;
}).RequireAuthorization();
RequireAuthorization 擴充方法需要路由定義的授權。 針對您新增至專案的任何控制器,請將 [Authorize] 屬性 新增至控制器或動作。
設定後端 Web API 專案 (MinimalApiJwt)
在專案的MinimalApiJwt檔案中,於JwtBearerOptions呼叫的AddJwtBearer中設定Program專案。
針對 Web API 應用程式的註冊,Weather.Get 範圍是在 Entra 或 Azure 入口網站的 Expose an API 中設定。
Authority 設定 OIDC 呼叫的權限。
jwtOptions.Authority = "{AUTHORITY}";
以下範例使用租戶 ID 為 , aaaabbbb-0000-cccc-1111-dddd2222eeee 目錄名稱為 contoso。
如果應用程式已在 ME-ID 承租者中註冊,授權機構應與識別提供者所返回的 JWT 的發行者(iss)匹配。
jwtOptions.Authority = "https://sts.windows.net/aaaabbbb-0000-cccc-1111-dddd2222eeee";
如果該應用程式註冊在 Microsoft Entra 外部 ID 租戶中:
jwtOptions.Authority = "https://contoso.ciamlogin.com/aaaabbbb-0000-cccc-1111-dddd2222eeee/v2.0";
如果應用程式已在 AAD B2C 租用戶中註冊:
jwtOptions.Authority = "https://login.microsoftonline.com/aaaabbbb-0000-cccc-1111-dddd2222eeee/v2.0";
Note
自 2025 年 5 月 1 日起,Azure Active Directory B2C 不再提供給新客戶提供服務。 AAD B2C 租戶適用於 2025 年 5 月 1 日前建立帳戶的客戶,至 2030 年皆可使用。 欲了解更多資訊,請參閱 Azure AD B2C:常見問題(FAQ)。
Audience 會為任何已接收的 JWT 存取令牌設定對象。
jwtOptions.Audience = "{AUDIENCE}";
在 Entra 或 Azure 入口網站中,將值與在 [公開 API] 下新增 Weather.Get 範疇時所配置的 應用程式識別碼 URI 的路徑相符。 請勿在值中包含範圍名稱 "Weather.Get"。
下列範例使用的應用程式 (用戶端) 識別碼 11112222-bbbb-3333-cccc-4444dddd5555。 第三個例子使用了contoso.onmicrosoft.com租戶網域。
ME-ID 租使用者範例:
jwtOptions.Audience = "api://11112222-bbbb-3333-cccc-4444dddd5555";
Microsoft Entra 外部識別碼租戶:
jwtOptions.Audience = "11112222-bbbb-3333-cccc-4444dddd5555";
AAD B2C 租使用者範例:
jwtOptions.Audience = "https://contoso.onmicrosoft.com/11112222-bbbb-3333-cccc-4444dddd5555";
設定伺服器專案 (BlazorWebAppEntra)
AddMicrosoftIdentityWebApp從 Microsoft Identity Web (Microsoft.Identity.WebNuGet 套件、API 文件)設定在專案的BlazorWebAppEntra檔案中。
從 Entra 或 Azure 入口網站中的應用程式註冊,取得應用程式(用戶端)識別碼、租戶(出版本)網域和目錄(租戶)識別碼。 應用程式識別碼 URI 是從 Web API 的Weather.Get註冊中取得的作用域。 從入口網站取得應用程式識別碼 URI 時,請勿包含範圍名稱。
認證設定依租戶類型而異:
ME-ID 租戶配置
此條款適用於註冊於 Microsoft Entra ID 或 Azure AAD B2C 租戶的應用程式。
在 BlazorWebAppEntra 項目的 Program 檔案中,提供以下 Microsoft Identity Web 組態中的佔位符值:
builder.Services.AddAuthentication(OpenIdConnectDefaults.AuthenticationScheme)
.AddMicrosoftIdentityWebApp(msIdentityOptions =>
{
msIdentityOptions.CallbackPath = "/signin-oidc";
msIdentityOptions.ClientId = "{CLIENT ID (BLAZOR APP)}";
msIdentityOptions.Domain = "{DIRECTORY NAME}.onmicrosoft.com";
msIdentityOptions.Instance = "https://login.microsoftonline.com/";
msIdentityOptions.ResponseType = "code";
msIdentityOptions.TenantId = "{TENANT ID}";
})
.EnableTokenAcquisitionToCallDownstreamApi()
.AddDownstreamApi("DownstreamApi", configOptions =>
{
configOptions.BaseUrl = "{BASE ADDRESS}";
configOptions.Scopes = ["{APP ID URI}/Weather.Get"];
})
.AddDistributedTokenCaches();
為請求轉換器提供相同的下游 API 範圍:
List<string> scopes = ["{APP ID URI}/Weather.Get"];
上述設定中的占位符:
-
{CLIENT ID (BLAZOR APP)}:應用程式 (用戶端) 識別碼。 -
{DIRECTORY NAME}:租戶(發佈者)網域的目錄名稱。 -
{TENANT ID}:目錄(租用戶)識別碼。 -
{BASE ADDRESS}:Web API 的基位址。 -
{APP ID URI}:Web API 範圍的應用程式識別碼 URI。 下列格式之一會被使用,其中{CLIENT ID (WEB API)}佔位元是 Web API 的 Entra 註冊的用戶端識別碼,而{DIRECTORY NAME}佔位元是承租者(發行者)網域的目錄名稱(例如:contoso)。- ME-ID 租戶格式:
api://{CLIENT ID (WEB API)} - B2C 租戶格式:
https://{DIRECTORY NAME}.onmicrosoft.com/{CLIENT ID (WEB API)}
- ME-ID 租戶格式:
Example:
builder.Services.AddAuthentication(OpenIdConnectDefaults.AuthenticationScheme)
.AddMicrosoftIdentityWebApp(msIdentityOptions =>
{
msIdentityOptions.CallbackPath = "/signin-oidc";
msIdentityOptions.ClientId = "00001111-aaaa-2222-bbbb-3333cccc4444";
msIdentityOptions.Domain = "contoso.onmicrosoft.com";
msIdentityOptions.Instance = "https://login.microsoftonline.com/";
msIdentityOptions.ResponseType = "code";
msIdentityOptions.TenantId = "aaaabbbb-0000-cccc-1111-dddd2222eeee";
})
.EnableTokenAcquisitionToCallDownstreamApi()
.AddDownstreamApi("DownstreamApi", configOptions =>
{
configOptions.BaseUrl = "https://localhost:7277";
configOptions.Scopes =
["api://11112222-bbbb-3333-cccc-4444dddd5555/Weather.Get"];
})
.AddDistributedTokenCaches();
Example:
List<string> scopes = ["api://11112222-bbbb-3333-cccc-4444dddd5555/Weather.Get"];
Microsoft Entra 外部 ID 配置
本節適用於註冊於 Microsoft Entra 外部 ID 租戶的應用程式。
在 BlazorWebAppEntra 項目的 Program 檔案中,提供以下 Microsoft Identity Web 組態中的佔位符值:
builder.Services.AddAuthentication(OpenIdConnectDefaults.AuthenticationScheme)
.AddMicrosoftIdentityWebApp(msIdentityOptions =>
{
msIdentityOptions.CallbackPath = "/signin-oidc";
msIdentityOptions.Authority = "https://{DIRECTORY NAME}.ciamlogin.com/{TENANT ID}/v2.0";
msIdentityOptions.ClientId = "{CLIENT ID (BLAZOR APP)}";
msIdentityOptions.ResponseType = "code";
})
.EnableTokenAcquisitionToCallDownstreamApi()
.AddDownstreamApi("DownstreamApi", configOptions =>
{
configOptions.BaseUrl = "{BASE ADDRESS}";
configOptions.Scopes = ["{APP ID URI}/Weather.Get"];
})
.AddDistributedTokenCaches();
為請求轉換器提供相同的下游 API 範圍:
List<string> scopes = ["{APP ID URI}/Weather.Get"];
上述設定中的占位符:
-
{DIRECTORY NAME}:租戶(發佈者)網域的目錄名稱。 -
{CLIENT ID (BLAZOR APP)}:應用程式 (用戶端) 識別碼。 -
{BASE ADDRESS}:Web API 的基位址。 -
{APP ID URI}:Web API 範圍的應用程式識別碼 URI。 下列格式之一會被使用,其中{CLIENT ID (WEB API)}佔位元是 Web API 的 Entra 註冊的用戶端識別碼,而{DIRECTORY NAME}佔位元是承租者(發行者)網域的目錄名稱(例如:contoso)。- ME-ID 或Microsoft Entra 外部 ID 租戶格式:
api://{CLIENT ID (WEB API)} - B2C 租戶格式:
https://{DIRECTORY NAME}.onmicrosoft.com/{CLIENT ID (WEB API)}
- ME-ID 或Microsoft Entra 外部 ID 租戶格式:
Example:
builder.Services.AddAuthentication(OpenIdConnectDefaults.AuthenticationScheme)
.AddMicrosoftIdentityWebApp(msIdentityOptions =>
{
msIdentityOptions.CallbackPath = "/signin-oidc";
msIdentityOptions.Authority = "https://contoso.ciamlogin.com/aaaabbbb-0000-cccc-1111-dddd2222eeee/v2.0";
msIdentityOptions.ClientId = "00001111-aaaa-2222-bbbb-3333cccc4444";
msIdentityOptions.ResponseType = "code";
})
.EnableTokenAcquisitionToCallDownstreamApi()
.AddDownstreamApi("DownstreamApi", configOptions =>
{
configOptions.BaseUrl = "https://localhost:7277";
configOptions.Scopes = ["api://11112222-bbbb-3333-cccc-4444dddd5555/Weather.Get"];
})
.AddDistributedTokenCaches();
Example:
List<string> scopes = ["api://11112222-bbbb-3333-cccc-4444dddd5555/Weather.Get"];
Warning
生產應用程式應該使用適用於生產環境的分佈式令牌快取供應商。 否則,在某些情況下,應用程式可能會效能不佳。 如需詳細資訊,請參閱 使用生產分散式令牌快取提供者 一節。
回呼路徑 (CallbackPath) 必須符合在 Entra 或 Azure 入口網站 中註冊應用程式時所設定的重新導向 URI(登入回呼路徑)。 應用程式註冊的 驗證 設定頁面中設定路徑。 預設值 CallbackPath 為 /signin-oidc、註冊的重新導向 URI https://localhost/signin-oidc (不需要埠)。
SignedOutCallbackPath是使用者代理程式從Entra登出後,OpenID Connect處理程式在應用程式基底路徑內攔截的要求路徑。 範例應用程式不會設定路徑的值,因為會使用預設值 「/signout-callback-oidc」。。 攔截要求之後,如果指定,OpenID Connect 處理程式會重新導向至 SignedOutRedirectUri 或 RedirectUri。
Warning
請勿在用戶端程式代碼中儲存應用程式密碼、連接字串、認證、密碼、個人標識元(PIN)、私人 C#/.NET 程式代碼或私鑰/令牌,這一律不安全。 在測試/預備和生產環境中,伺服器端 Blazor 程序代碼和 Web API 應該使用安全驗證流程,以避免在專案程式代碼或組態檔內維護認證。 在本機開發測試之外,建議您避免使用環境變數來儲存敏感數據,因為環境變數不是最安全的方法。 針對本機開發測試, 建議使用秘密管理員工具 來保護敏感數據。 如需詳細資訊,請參閱 安全地維護敏感數據和認證。
建立客戶端密碼
本節僅適用於的伺服器 Blazor Web App專案。
使用下列任一或兩種方法,將客戶端密碼提供給應用程式:
- 秘密管理員工具:秘密管理員工具會將私人數據儲存在本機計算機上,而且只會在本機開發期間使用。
- Azure 金鑰保存庫:您可以將用戶端密碼儲存在密鑰保存庫中,以用於任何環境,包括在本機工作時用於開發環境。 有些開發人員偏好使用金鑰保存庫進行預備和生產部署,並使用秘密管理員工具來進行本機開發。
強烈建議您避免將客戶端密碼儲存在專案程式代碼或組態檔中。 使用安全驗證流程,例如本節中任一或兩種方法。
秘密管理員工具
秘密 管理員工具 可以在組態金鑰 AzureAd:ClientSecret下儲存伺服器應用程式的客戶端密碼。
尚未初始化伺服器應用程式以用於秘密管理員工具。 使用命令殼層,例如 Visual Studio 中的開發人員 PowerShell 命令殼層,執行下列命令。 在執行命令之前,請將 目錄與 cd 命令變更為伺服器項目的目錄。 命令會在伺服器應用程式項目檔中建立使用者機密識別碼(<UserSecretsId>),工具會在內部使用此識別碼來追蹤應用程式的機密:
dotnet user-secrets init
執行下列命令來設定客戶端密碼。
{SECRET} 佔位符是從應用程式的 Entra 註冊取得的客戶端密碼。
dotnet user-secrets set "AzureAd:ClientSecret" "{SECRET}"
如果使用 Visual Studio,您可以在 方案總管 中以滑鼠右鍵按兩下伺服器專案,然後選取 [管理用戶密碼],以確認密碼已設定。
Azure Key Vault
Azure 金鑰保存庫 提供安全的方法來提供應用程式的用戶端密碼給應用程式。
若要建立密鑰保存庫並設定用戶端密碼,請參閱關於 Azure 金鑰保存庫 秘密 (Azure 檔),其中會跨鏈接資源以開始使用 Azure 金鑰保存庫。 若要在本節中實作程序代碼,請在建立密鑰保存庫和秘密時,記錄來自 Azure 的密鑰保存庫 URI 和秘密名稱。 針對本節中的範例,秘密名稱為 “BlazorWebAppEntraClientSecret ” ”
在 Entra 或 Azure 入口網站中建立金鑰保存庫時:
將金鑰保存庫設定為使用 Azure 角色型存取控制 (RABC)。 如果您未在 Azure 虛擬網路上運行,包括用於本機開發和測試,請確認在 網路步驟中公用存取已啟用。 啟用公用存取只會公開金鑰保存庫端點。 存取仍然需要已驗證的帳戶。
建立 Azure 受控 Identity 角色(或將角色新增至您打算使用的現有受控 Identity 角色),並搭配 Key Vault 秘密使用者 角色。 將受控Identity指派給裝載部署的 Azure App Service:設定>Identity>使用者指派>新增。
Note
如果您也計劃使用 Azure CLI 或 Visual Studio 的 Azure 服務驗證,在本機以授權使用者身份執行應用程式以存取金鑰保存庫,請將開發人員的 Azure 使用者帳戶新增至存取控制 (IAM),並賦予金鑰保存庫秘密用戶角色。 如果您想要透過Visual Studio使用 Azure CLI,請從開發人員 PowerShell 面板執行
az login命令,並遵循提示向租用戶進行驗證。
若要在本節中實作程序代碼,請在建立密鑰保存庫和秘密時,記錄來自 Azure 的金鑰保存庫 URI(例如:“https://contoso.vault.azure.net/”、需要尾端斜線)和秘密名稱(例如:“”。BlazorWebAppEntraClientSecret
Important
在金鑰保存庫中建立的機密資料會設有到期日。 請務必追蹤金鑰保存庫秘密何時到期,並在該日期通過之前為應用程式建立新的秘密。
將下列 AzureHelper 類別新增至伺服器專案。
GetKeyVaultSecret 方法會從金鑰保存庫擷取秘密。 調整命名空間 (BlazorSample.Helpers) 以符合您的專案命名空間配置。
Helpers/AzureHelper.cs:
using Azure.Core;
using Azure.Security.KeyVault.Secrets;
namespace BlazorWebAppEntra.Helpers;
public static class AzureHelper
{
public static string GetKeyVaultSecret(string vaultUri,
TokenCredential credential, string secretName)
{
var client = new SecretClient(new Uri(vaultUri), credential);
var secret = client.GetSecretAsync(secretName).Result;
return secret.Value.Value;
}
}
Note
上述範例會使用 DefaultAzureCredential 來簡化驗證,同時開發部署至 Azure 的應用程式,方法是將 Azure 主控環境中所使用的認證與本機開發中使用的認證結合在一起。 移至生產環境時,替代方式是較佳的選擇,例如 ManagedIdentityCredential。 如需詳細資訊,請參閱 使用系統指派的受控識別向 Azure 資源驗證 Azure 裝載的 .NET 應用程式。
在伺服器專案檔案 Program 中註冊服務的位置,請使用下列程式代碼取得並套用客戶端密碼:
TokenCredential? credential;
if (builder.Environment.IsProduction())
{
credential = new ManagedIdentityCredential("{MANAGED IDENTITY CLIENT ID}");
}
else
{
// Local development and testing only
DefaultAzureCredentialOptions options = new()
{
// Specify the tenant ID to use the dev credentials when running the app locally
// in Visual Studio.
VisualStudioTenantId = "{TENANT ID}",
SharedTokenCacheTenantId = "{TENANT ID}"
};
credential = new DefaultAzureCredential(options);
}
在設定MicrosoftIdentityOptions後,呼叫GetKeyVaultSecret以接收並指派應用程式的客戶端密碼:
msIdentityOptions.ClientSecret = AzureHelper.GetKeyVaultSecret("{VAULT URI}",
credential, "{SECRET NAME}");
{MANAGED IDENTITY CLIENT ID}:Azure 託管的 Identity 客戶端識別碼 (GUID)。
{TENANT ID}:目錄(租用戶)識別碼。 範例:aaaabbbb-0000-cccc-1111-dddd2222eeee
{VAULT URI}:金鑰保存庫 URI。 請於 URI 結尾加入斜線。 範例:https://contoso.vault.azure.net/
{SECRET NAME}:秘密名稱。 範例:BlazorWebAppEntraClientSecret
設定用來根據應用程式的環境設定檔來提供專屬的金鑰保管庫和密鑰名稱。 例如,您可以為appsettings.Development.json開發環境、appsettings.Staging.json預備階段,以及appsettings.Production.json生產部署提供不同的組態值。 如需詳細資訊,請參閱 ASP.NET Core Blazor 組態。
僅將名稱和角色權利要求序列化
在Program 檔案中,所有聲明都會藉由將SerializeAllClaims設定為true來進行串行化。 如果您只想針對 CSR 序列化名稱與角色聲明,請移除選項,或將其設定為 false。
使用 JSON 組態提供者設定應用程式設定
範例解決方案專案會在其檔案中Identity設定Microsoft Program Web 和 JWT 持有人驗證,以便使用 C# 自動完成來探索組態設定。 專業應用程式通常會使用 設定提供者 來設定 OIDC 選項,例如預設 的 JSON 設定提供者。 JSON 組態提供者會從應用程式配置檔 appsettings.json/appsettings.{ENVIRONMENT}.json載入組態,其中 {ENVIRONMENT} 佔位元是應用程式的 運行時間環境。 請遵循本節中的指引,使用應用程式配置檔進行組態。
在專案的應用程式設定檔 (appsettings.json) BlazorWebAppEntra 中,新增下列 JSON 組態:
{
"AzureAd": {
"CallbackPath": "/signin-oidc",
"ClientId": "{CLIENT ID (BLAZOR APP)}",
"Domain": "{DIRECTORY NAME}.onmicrosoft.com",
"Instance": "https://login.microsoftonline.com/",
"ResponseType": "code",
"TenantId": "{TENANT ID}"
},
"DownstreamApi": {
"BaseUrl": "{BASE ADDRESS}",
"Scopes": ["{APP ID URI}/Weather.Get"]
}
}
更新上述組態中的佔位元,以符合應用程式在檔案中使用的 Program 值:
-
{CLIENT ID (BLAZOR APP)}:應用程式 (用戶端) 識別碼。 -
{DIRECTORY NAME}:租戶(發佈者)網域的目錄名稱。 -
{TENANT ID}:目錄(租用戶)識別碼。 -
{BASE ADDRESS}:Web API 的基位址。 -
{APP ID URI}:Web API 範圍的應用程式識別碼 URI。 下列格式之一會被使用,其中{CLIENT ID (WEB API)}佔位元是 Web API 的 Entra 註冊的用戶端識別碼,而{DIRECTORY NAME}佔位元是承租者(發行者)網域的目錄名稱(例如:contoso)。- ME-ID 租戶格式:
api://{CLIENT ID (WEB API)} - B2C 租戶格式:
https://{DIRECTORY NAME}.onmicrosoft.com/{CLIENT ID (WEB API)}
- ME-ID 租戶格式:
Example:
"AzureAd": {
"CallbackPath": "/signin-oidc",
"ClientId": "00001111-aaaa-2222-bbbb-3333cccc4444",
"Domain": "contoso.onmicrosoft.com",
"Instance": "https://login.microsoftonline.com/",
"ResponseType": "code",
"TenantId": "aaaabbbb-0000-cccc-1111-dddd2222eeee"
},
"DownstreamApi": {
"BaseUrl": "https://localhost:7277",
"Scopes": ["api://11112222-bbbb-3333-cccc-4444dddd5555/Weather.Get"]
}
更新上述組態中的任何其他值,以符合檔案中使用的 Program 自定義/非預設值。
驗證產生器會自動挑選組態。
在檔案中 Program 進行下列變更:
builder.Services.AddAuthentication(OpenIdConnectDefaults.AuthenticationScheme)
- .AddMicrosoftIdentityWebApp(msIdentityOptions =>
- {
- msIdentityOptions.CallbackPath = "...";
- msIdentityOptions.ClientId = "...";
- msIdentityOptions.Domain = "...";
- msIdentityOptions.Instance = "...";
- msIdentityOptions.ResponseType = "...";
- msIdentityOptions.TenantId = "...";
- })
+ .AddMicrosoftIdentityWebApp(builder.Configuration.GetSection("AzureAd"))
.EnableTokenAcquisitionToCallDownstreamApi()
- .AddDownstreamApi("DownstreamApi", configOptions =>
- {
- configOptions.BaseUrl = "...";
- configOptions.Scopes = ["..."];
- })
+ .AddDownstreamApi("DownstreamApi", builder.Configuration.GetSection("DownstreamApi"))
.AddDistributedTokenCaches();
- List<string> scopes = ["{APP ID URI}/Weather.Get"];
- var accessToken = await tokenAcquisition.GetAccessTokenForUserAsync(scopes);
+ var configuration = transformContext.HttpContext.RequestServices.GetRequiredService<IConfiguration>();
+ var scopes = configuration.GetSection("DownstreamApi:Scopes").Get<IEnumerable<string>>();
+ var accessToken = await tokenAcquisition.GetAccessTokenForUserAsync(scopes ??
+ throw new InvalidOperationException("No downstream API scopes!"));
Note
生產應用程式應該使用適用於生產環境的分佈式令牌快取供應商。 否則,在某些情況下,應用程式可能會效能不佳。 如需詳細資訊,請參閱 使用生產分散式令牌快取提供者 一節。
在 MinimalApiJwt 專案中,將下列應用程式設定組態新增至 appsettings.json 檔案:
"Authentication": {
"Schemes": {
"Bearer": {
"Authority": "https://sts.windows.net/{TENANT ID (WEB API)}",
"ValidAudiences": ["{APP ID URI (WEB API)}"]
}
}
},
更新上述組態中的佔位元,以符合應用程式在檔案中使用的 Program 值:
-
{TENANT ID (WEB API)}:Web API 的租用戶標識符。 -
{APP ID URI (WEB API)}:Web API 的應用程式識別碼 URI。
權威機構格式採用下列模式:
- ME-ID 租戶類型:
https://sts.windows.net/{TENANT ID} - Microsoft Entra 外部識別碼:
https://{DIRECTORY NAME}.ciamlogin.com/{TENANT ID}/v2.0 - B2C 租戶類型:
https://login.microsoftonline.com/{TENANT ID}/v2.0
物件格式採用下列模式({CLIENT ID}是 Web API 的用戶端識別元,{DIRECTORY NAME}例如目錄名稱): contoso
- ME-ID 租戶類型:
api://{CLIENT ID} - Microsoft Entra 外部識別碼:
{CLIENT ID} - B2C 租戶類型:
https://{DIRECTORY NAME}.onmicrosoft.com/{CLIENT ID}
JWT 持有人驗證產生器會自動挑選組態。
從 Program 檔案中移除下列幾行:
- jwtOptions.Authority = "...";
- jwtOptions.Audience = "...";
如需設定的詳細資訊,請參閱下列資源:
- ASP.NET Core 中的 組態
- ASP.NET Core Blazor 設定
使用生產分散式令牌快取提供者
當呼叫 AddDistributedTokenCaches 時,會建立記憶體中的分散式令牌快取,以確保分散式令牌快取有可供使用的基礎實作。
生產 Web 應用程式和 Web API 應該使用生產分散式令牌快取(例如: Redis、 Microsoft SQL Server、 Microsoft Azure Cosmos DB)。
Note
若要在單一計算機上進行本機開發和測試,您可以使用記憶體內部令牌快取,而不是分散式令牌快取:
builder.Services.AddInMemoryTokenCaches();
稍後在開發和測試期間,採用生產分散式令牌快取提供者。
AddDistributedMemoryCache 新增了一個默認的 IDistributedCache 實作,將快取項目儲存在記憶體中,這用於Microsoft Identity Web的令牌快取。
分散式令牌快取是由MsalDistributedTokenCacheAdapterOptions設定:
- 在進行偵錯的開發中,您可以將 設定 DisableL1Cache 為
true來停用 L1 快取。 請務必將它重設為false生產環境。 - 設定 L1
L1CacheOptions.SizeLimit快取的大小上限,以防止快取佔用過多伺服器的記憶體。 預設值為 500 MB。 - 為了進行偵錯的開發,您可以將 Encrypt 設定為
false,這是預設值,以停用靜態令牌加密。 請務必將它重設為true生產環境。 - 使用 SlidingExpiration 設定快取中的令牌移除。 預設值為1小時。
- 如需詳細資訊,包括 L2 快取失敗回呼(OnL2CacheFailure)和非同步 L2 快取寫入的指引(EnableAsyncL2Write),請參閱 MsalDistributedTokenCacheAdapterOptions 和 令牌快取序列化:分散式令牌快取。
builder.Services.AddDistributedMemoryCache();
builder.Services.Configure<MsalDistributedTokenCacheAdapterOptions>(
options =>
{
// The following lines that are commented out reflect
// default values. We recommend overriding the default
// value of Encrypt to encrypt tokens at rest.
//options.DisableL1Cache = false;
//options.L1CacheOptions.SizeLimit = 500 * 1024 * 1024;
options.Encrypt = true;
//options.SlidingExpiration = TimeSpan.FromHours(1);
});
AddDistributedMemoryCache需要引用Microsoft.Extensions.Caching.Memory NuGet 套件。
若要設定生產分散式快取提供者,請參閱 ASP.NET Core 中的分散式快取。
Warning
在將應用程式部署至生產環境時,務必將記憶體中的分散式令牌快取替換為實際運作的令牌快取提供者。 如果您無法採用生產分散式令牌快取提供者,應用程式可能會大幅降低效能。
如需詳細資訊,請參閱 令牌快取串行化:分散式快取。 不過,顯示的程式代碼範例不適用於 ASP.NET Core 應用程式,其會透過 AddDistributedMemoryCache設定分散式快取,而不是 AddDistributedTokenCache。
在生產環境中使用共用的數據保護密鑰圈,讓 Web 伺服器陣列中的應用程式實例在 MsalDistributedTokenCacheAdapterOptions.Encrypt 設定為 true 時可以解密令牌。
Note
若要在單一計算機上進行早期開發和本機測試,您可以稍後將 設定 Encrypt 為 false 並設定共用數據保護密鑰通道:
options.Encrypt = false;
稍後在開發和測試期間,啟用令牌加密,並採用共用數據保護密鑰通道。
下列範例示範如何針對共用金鑰環使用 Azure Blob 儲存體和 Azure Key Vault(PersistKeysToAzureBlobStorage/ProtectKeysWithAzureKeyVault)。 服務組態是用於示範的基底案例。 在部署生產應用程式之前,請先熟悉 Azure 服務,並使用本節結尾連結的 Azure 服務專用檔集來採用最佳做法。
確認 伺服器專案中 Blazor Web App存在下列套件:
Note
在繼續進行下列步驟之前,請先確認該應用程式已在 Microsoft Entra 註冊。
通常在實作生產分散式令牌快取提供者的同時,也會實作以下程式碼。 Azure 和 Azure 外部的其他選項都可用於跨多個應用程式實例管理數據保護密鑰,但範例應用程式示範如何使用 Azure 服務。
設定 Azure Blob 記憶體以維護資料保護密鑰。 請遵循 ASP.NET Core 中金鑰儲存提供者中的指引。
設定 Azure Key Vault 以在靜止狀態下加密資料保護密鑰。 請遵循設定 ASP.NET Core Data Protection 中的指引。
在註冊服務的檔案中使用 Program 下列代碼:
TokenCredential? credential;
if (builder.Environment.IsProduction())
{
credential = new ManagedIdentityCredential("{MANAGED IDENTITY CLIENT ID}");
}
else
{
// Local development and testing only
DefaultAzureCredentialOptions options = new()
{
// Specify the tenant ID to use the dev credentials when running the app locally
// in Visual Studio.
VisualStudioTenantId = "{TENANT ID}",
SharedTokenCacheTenantId = "{TENANT ID}"
};
credential = new DefaultAzureCredential(options);
}
builder.Services.AddDataProtection()
.SetApplicationName("BlazorWebAppEntra")
.PersistKeysToAzureBlobStorage(new Uri("{BLOB URI}"), credential)
.ProtectKeysWithAzureKeyVault(new Uri("{KEY IDENTIFIER}"), credential);
您可以將任何應用程式名稱傳遞至 SetApplicationName。 只要確認所有應用程式部署都使用相同的值。
{MANAGED IDENTITY CLIENT ID}:Azure 託管的 Identity 客戶端識別碼 (GUID)。
{TENANT ID}:租使用者標識碼。
{BLOB URI}:金鑰檔案的完整 URI。 當您建立密鑰檔案時,Azure 記憶體會產生 URI。 請勿使用 SAS。
{KEY IDENTIFIER}:用於密鑰加密的 Azure Key Vault 金鑰標識碼。 存取原則可讓應用程式使用 Get、 Unwrap Key和 Wrap Key 許可權存取金鑰保存庫。 建立金鑰後,可以從 Entra 或 Azure 入口網站中的金鑰取得金鑰版本。 如果您啟用金鑰儲存庫金鑰的自動調整,請確定您在應用程式的金鑰儲存庫組態中使用無版本金鑰標識碼,其中識別子結尾不會放置任何金鑰 GUID(例如:)。 https://contoso.vault.azure.net/keys/data-protection
Note
在非生產環境中,上述範例會使用 DefaultAzureCredential 來簡化驗證,同時開發部署至 Azure 的應用程式,方法是將 Azure 主控環境中所使用的認證與本機開發中使用的認證結合在一起。 如需詳細資訊,請參閱 使用系統指派的受控識別向 Azure 資源驗證 Azure 裝載的 .NET 應用程式。
或者,您也可以設定應用程式,以使用 JSON 組態提供者,從應用程式設定檔提供值。 將下列內容新增至應用程式設定檔:
"DistributedTokenCache": {
"DisableL1Cache": false,
"L1CacheSizeLimit": 524288000,
"Encrypt": true,
"SlidingExpirationInHours": 1
},
"DataProtection": {
"BlobUri": "{BLOB URI}",
"KeyIdentifier": "{KEY IDENTIFIER}"
}
範例 DataProtection 區段:
"DataProtection": {
"BlobUri": "https://contoso.blob.core.windows.net/data-protection/keys.xml",
"KeyIdentifier": "https://contoso.vault.azure.net/keys/data-protection"
}
Note
上述範例中的金鑰標識碼 是無版本。 標識子結尾沒有 GUID 金鑰版本。 如果您選擇為金鑰設定自動金鑰輪替,這特別重要。 如需詳細資訊,請參閱 在 Azure Key Vault 中設定密碼編譯密鑰自動輪替:金鑰輪替原則。
在檔案中 Program 進行下列變更:
builder.Services.Configure<MsalDistributedTokenCacheAdapterOptions>(
options =>
{
+ var config = builder.Configuration.GetSection("DistributedTokenCache");
- options.DisableL1Cache = false;
+ options.DisableL1Cache = config.GetValue<bool>("DisableL1Cache");
- options.L1CacheOptions.SizeLimit = 500 * 1024 * 1024;
+ options.L1CacheOptions.SizeLimit = config.GetValue<long>("L1CacheSizeLimit");
- options.Encrypt = true;
+ options.Encrypt = config.GetValue<bool>("Encrypt");
- options.SlidingExpiration = TimeSpan.FromHours(1);
+ options.SlidingExpiration =
+ TimeSpan.FromHours(config.GetValue<int>("SlidingExpirationInHours"));
});
- builder.Services.AddDataProtection()
- .SetApplicationName("BlazorWebAppEntra")
- .PersistKeysToAzureBlobStorage(new Uri("{BLOB URI}"), credential)
- .ProtectKeysWithAzureKeyVault(new Uri("{KEY IDENTIFIER}"), credential);
在 Program 檔案中配置服務的地方新增以下程式碼:
var config = builder.Configuration.GetSection("DataProtection");
builder.Services.AddDataProtection()
.SetApplicationName("BlazorWebAppEntra")
.PersistKeysToAzureBlobStorage(
new Uri(config.GetValue<string>("BlobUri") ??
throw new Exception("Missing Blob URI")),
credential)
.ProtectKeysWithAzureKeyVault(
new Uri(config.GetValue<string>("KeyIdentifier") ??
throw new Exception("Missing Key Identifier")),
credential);
如需使用共用資料保護密鑰通道和金鑰儲存提供者的詳細資訊,請參閱下列資源:
- ASP.NET Core 中的金鑰儲存體提供者
- 設定核心數據保護 ASP.NET
- 在 ASP.NET Core 應用程式中使用 Azure SDK for .NET
- 在 Web 農場中託管 ASP.NET Core:資料保護
- 設定核心數據保護 ASP.NET
- ASP.NET Core 中的金鑰儲存體提供者
- Azure Key Vault 文件
- Azure 儲存體文件
- 使用 Azure 角色型訪問控制來提供 Key Vault 金鑰、憑證和秘密的存取權
YARP 轉發器目的地前綴
伺服器 Blazor Web App 專案的 YARP 轉發器,其中使用者的存取令牌會附加至 MinimalApiJwt Web API 呼叫,指定的 https://weatherapi 目的地前置詞。 此值與AddProject專案的Program文件中傳遞到Aspire.AppHost的專案名稱相符。
伺服器專案中的 Blazor Web App 轉發器 (BlazorWebAppEntra):
app.MapForwarder("/weather-forecast", "https://weatherapi", transformBuilder =>
{
...
}).RequireAuthorization();
在應用程式主機專案(Program)的Aspire檔案中,相符的專案名稱為Aspire.AppHost:
var weatherApi = builder.AddProject<Projects.MinimalApiJwt>("weatherapi");
在部署 Blazor Web App 至生產環境時,不需要變更 YARP 轉送系統的目的地的前置詞。 Microsoft Identity Web 下游 API 套件會使用透過組態傳遞的基底 URI,從 ServerWeatherForecaster進行 Web API 呼叫,而不是 YARP 轉寄站的目的地前置詞。 在生產環境中,YARP 轉寄站只會轉換要求,並新增使用者的存取令牌。
登出後重新導向至首頁
LogInOrOut 元件 (Layout/LogInOrOut.razor) 會將傳回 URL (ReturnUrl) 的隱藏欄位設定為目前的 URL(currentURL)。 當使用者註銷應用程式時,身份提供者會將使用者傳回他們註銷的頁面。如果使用者從安全頁面註銷,則會傳回相同的安全頁面,並重新進行驗證程序。 當使用者需要定期變更帳戶時,此驗證流程是合理的。
或者,使用下列 LogInOrOut 元件,該元件在登出時不會提供返回 URL。
Layout/LogInOrOut.razor:
<div class="nav-item px-3">
<AuthorizeView>
<Authorized>
<form action="authentication/logout" method="post">
<AntiforgeryToken />
<button type="submit" class="nav-link">
<span class="bi bi-arrow-bar-left-nav-menu" aria-hidden="true">
</span> Logout
</button>
</form>
</Authorized>
<NotAuthorized>
<a class="nav-link" href="authentication/login">
<span class="bi bi-person-badge-nav-menu" aria-hidden="true"></span>
Login
</a>
</NotAuthorized>
</AuthorizeView>
</div>
天氣數據安全性
如需此應用程式如何保護其天氣數據的詳細資訊,請參閱 Blazor Web App保護 中的數據。
Troubleshoot
Logging
伺服器應用程式是標準 ASP.NET Core 應用程式。 請參閱 ASP.NET Core 記錄指導,在伺服器應用程式啟用較低的記錄層級。
若要啟用Blazor WebAssembly驗證的除錯或追蹤記錄,請參閱中的Blazor一節,並確保文章版本選擇器設為 .NET 7 或更新版本中的 ASP.NET Core。
常見錯誤
偵錯工具在登出時因例外情況暫停,使用 Microsoft Entra 外部標識碼。
下列例外狀況會在使用 Microsoft Entra 外部識別碼 註銷期間停止 Visual Studio 調試程式:
Uncaught TypeError TypeError: Failed to execute 'postMessage' on 'Window': The provided value cannot be converted to a sequence.
例外狀況是從 Entra JavaScript 程式碼拋出,因此這不是 ASP.NET Core 的問題。 例外狀況不會影響生產環境中的應用程式功能,因此可以在本機開發測試期間忽略例外狀況。
應用程式或 Identity 提供者 (IP) 的設定錯誤
最常見的錯誤是由不正確的設定所造成。 以下是一些範例:
- 視案例的需求而定,遺漏或不正確的授權單位、執行個體、租用戶識別碼、租用戶網域、用戶端識別碼或重新導向 URI 會防止應用程式驗證用戶端。
- 不正確的要求範圍會防止用戶端存取伺服器 Web API 端點。
- 不正確或遺漏伺服器 API 權限會防止用戶端存取伺服器 Web API 端點。
- 在不同於 IP 應用程式註冊中重新導向 URI 所設定的連接埠上執行應用程式。 請注意,Microsoft Entra ID 和在
localhost開發測試位址執行的應用程式不需要連接埠,但應用程式的連接埠設定和執行應用程式的連接埠必須與非localhost位址相符。
本文中的配置範例,展示正確的設定。 請仔細查看設定,確定應用程式和 IP 是否設定錯誤。
如果設定顯示正確:
分析應用程式記錄檔。
使用瀏覽器的開發人員工具,檢查用戶端應用程式與 IP 或伺服器應用程式之間的網路流量。 通常,在提出要求之後,IP 或伺服器應用程式會傳回錯誤訊息或有導致問題的線索訊息給用戶端。 下列文章中可找到開發人員工具指導:
- Google Chrome (Google 文件)
- Microsoft Edge
- Mozilla Firefox (Mozilla 文件)
文件小組會回應文檔的意見反應和錯誤(從此頁面的意見反應區段提出問題),但是無法提供產品支援。 有數個公用支援論壇可用來協助針對應用程式進行疑難排解。 我們建議下列事項:
上述論壇並非由 Microsoft 擁有或控制。
針對非安全性、非敏感性和非機密可重現架構 BUG 報告,向 ASP.NET Core 產品單位提出問題。 在您徹底調查問題的原因而且無法自行解決,並取得公用支援論壇上社群的協助之前,請勿向產品單位提出問題。 產品單位無法針對因簡單設定錯誤或涉及第三方服務的使用案例而中斷的個別應用程式進行疑難排解。 如果報告具有敏感性或機密性質,或描述了攻擊者可能惡意探索的產品中潛在的安全性缺陷,請參閱 報告安全性問題和 BUG (
dotnet/aspnetcoreGitHub 存放庫)。ME-ID 未經授權的客戶端
info: Microsoft.AspNetCore.Authorization.DefaultAuthorizationService[2] 授權失敗。 不符合以下需求:DenyAnonymousAuthorizationRequirement:需要已驗證的使用者。
ME-ID 的登入回呼錯誤:
- 錯誤:
unauthorized_client - 描述:
AADB2C90058: The provided application is not configured to allow public clients.
若要解決此錯誤:
- 在 Azure 入口網站中,存取應用程式的資訊清單。
- 將
allowPublicClient屬性設定為null或true。
- 錯誤:
Cookie 和網站資料
Cookie 和網站資料可以在應用程式更新之間保存,並可介入測試和疑難排解。 進行應用程式程式碼變更、使用提供者的使用者帳戶變更,或提供者應用程式設定變更時,請清除下列內容:
- 使用者登錄 Cookie
- 應用程式 Cookie
- 已快取及儲存的網站資料
防止殘留的 cookie 和網站資料干擾測試和疑難排解的一種方法是:
- 設定瀏覽器
- 使用瀏覽器進行測試,您可以設定在每次關閉瀏覽器時刪除所有 cookie 和網站資料。
- 請確定瀏覽器已手動關閉或由 IDE 關閉,以便對應用程式、測試使用者或提供者設定進行任何變更。
- 使用自訂命令,在 Visual Studio 中以私人模式或無痕模式開啟瀏覽器:
- 從 Visual Studio 的 執行 按鈕開啟 瀏覽方式 對話方塊。
- 選取新增按鈕。
- 在 [程式] 欄位中提供瀏覽器的路徑。 下列可執行檔路徑是 Windows 10 的一般安裝位置。 如果您的瀏覽器安裝在不同的位置,或您不是使用 Windows 10,請提供瀏覽器可執行檔的路徑。
- Microsoft Edge:
C:\Program Files (x86)\Microsoft\Edge\Application\msedge.exe - Google Chrome:
C:\Program Files (x86)\Google\Chrome\Application\chrome.exe - Mozilla Firefox:
C:\Program Files\Mozilla Firefox\firefox.exe
- Microsoft Edge:
- 在「引數」 欄位中,提供瀏覽器用來在 InPrivate 或無痕模式中開啟的命令列選項。 某些瀏覽器需要應用程式的 URL。
- Microsoft Edge:使用
-inprivate。 - Google Chrome:使用
--incognito --new-window {URL},其中{URL}是要開啟的 URL 的預留位置(例如https://localhost:5001)。 - Mozilla Firefox:使用
-private -url {URL},其中{URL}占位符是要開啟的 URL 【例如https://localhost:5001】。
- Microsoft Edge:使用
- 在「親切名稱」 欄位中提供名稱。 例如:
Firefox Auth Testing。 - 選取確定按鈕。
- 若要避免針對使用應用程式測試的每個反覆項目選取瀏覽器設定檔,請使用 [設為預設值] 按鈕,將設定檔設定為預設值。
- 請確定瀏覽器已由 IDE 關閉,以便對應用程式、測試使用者或提供者設定進行任何變更。
應用程式升級
在升級開發電腦上的 .NET SDK 或變更應用程式內的套件版本之後,運作中的應用程式可能會立即失敗。 在某些情況下,執行主要升級時,不一致的套件可能會中斷應用程式。 大多數這些問題都可依照下列指示來進行修正:
- 從命令提示字元執行
dotnet nuget locals all --clear,以清除本機系統的 NuGet 套件快取。 - 刪除專案的
bin和obj資料夾。 - 還原並重建專案。
- 在重新部署應用程式之前,請先刪除伺服器上部署資料夾中的所有檔案。
Note
不支援使用與應用程式目標框架不相容的套件版本。 如需套件的相關資訊,請使用 NuGet Gallery。
從正確的項目啟動方案
Blazor Web App:
- 針對其中一個 Backend-for-Frontend (BFF) 模式範例,請從
Aspire/Aspire.AppHost專案啟動解決方案。 - 針對其中一個非 BFF 模式範例,請從 伺服器項目啟動方案。
Blazor Server:
從 伺服器專案啟動解決方案。
檢查使用者
下列 UserClaims 元件可以直接在應用程式中使用,或作為進一步自訂的基礎。
UserClaims.razor:
@page "/user-claims"
@using System.Security.Claims
@using Microsoft.AspNetCore.Authorization
@attribute [Authorize]
<PageTitle>User Claims</PageTitle>
<h1>User Claims</h1>
@if (claims.Any())
{
<ul>
@foreach (var claim in claims)
{
<li><b>@claim.Type:</b> @claim.Value</li>
}
</ul>
}
@code {
private IEnumerable<Claim> claims = Enumerable.Empty<Claim>();
[CascadingParameter]
private Task<AuthenticationState>? AuthState { get; set; }
protected override async Task OnInitializedAsync()
{
if (AuthState == null)
{
return;
}
var authState = await AuthState;
claims = authState.User.Claims;
}
}
其他資源
- 從 ASP.NET Core Blazor 應用程式呼叫 Web API:Microsoft 身分識別平台
- Microsoft身分識別平台文件
- Web API 檔 |Microsoft身分識別平臺
- 呼叫 Web API 的 Web API:呼叫 API:選項 2:使用協助程序類別呼叫下游 Web API
-
AzureAD/microsoft-identity-webGitHub 存放庫:實作 Microsoft Identity Web for Microsoft Entra ID 和 Azure Active Directory B2C for ASP.NET Core 應用程式的實用指導,包括應用程式範例和相關 Azure 文件的連結。 目前,Azure 文件尚未明確說明 Blazor Web App,但適用於 ME-ID 和 Azure 裝載的 Blazor Web App 的安裝與設定方式與任何 ASP.NET Core Web 應用程式一致。 -
AuthenticationStateProvider服務 - 管理 Blazor Web App中的驗證狀態
- Blazor Web App中的服務抽象