Poznámka:
Přístup k této stránce vyžaduje autorizaci. Můžete se zkusit přihlásit nebo změnit adresáře.
Přístup k této stránce vyžaduje autorizaci. Můžete zkusit změnit adresáře.
Poznámka:
Toto není nejnovější verze tohoto článku. Aktuální verzi najdete ve verzi .NET 10 tohoto článku.
Upozorňující
Tato verze ASP.NET Core se už nepodporuje. Další informace najdete v zásadách podpory .NET a .NET Core. Aktuální verzi najdete v tomto článku ve verzi .NET 9.
Tento článek vysvětluje, jak nakonfigurovat serverovou stranu Blazor pro další scénáře zabezpečení, včetně způsobu předávání tokenů do Blazor aplikace.
Poznámka:
Příklady kódu v tomto článku využívají návratové typy s možnou hodnotou null (NRT) a statickou analýzu stavu null kompilátoru .NET, které jsou podporovány v ASP.NET Core na .NET 6 nebo novějších verzích. Při cílení na .NET 5 nebo starší odeberte označení typu null (?) z string?, TodoItem[]?, WeatherForecast[]? a IEnumerable<GitHubBranch>? typy v příkladech článku.
Předání tokenů do aplikace na straně Blazor serveru
Tato část se týká Blazor Web App. Prohlédněte si Blazor Serverčást tohoto článku ve verzi .NET 7.
Pokud chcete pouze použít přístupové tokeny k volání webového Blazor Web App rozhraní API z pojmenovaného klienta HTTP, přečtěte si část Použití obslužné rutiny tokenu pro volání webového rozhraní API , která vysvětluje, jak použít DelegatingHandler implementaci pro připojení přístupového tokenu uživatele k odchozím požadavkům. Následující doprovodné materiály v této části jsou určené pro vývojáře, kteří potřebují přístupové tokeny, obnovovací tokeny a další vlastnosti ověřování na straně serveru pro jiné účely.
Pokud chcete uložit tokeny a další vlastnosti ověřování pro použití na straně serveru, Blazor Web Appdoporučujeme použít IHttpContextAccessor/HttpContext (IHttpContextAccessor, HttpContext). Čtení tokenů z HttpContext, včetně použití jako kaskádového parametru, je pomocí IHttpContextAccessor podporováno pro získání tokenů k použití během interaktivního vykreslování na serveru, pokud jsou tokeny získány během statického vykreslování na straně serveru (statické SSR) nebo předběžného vykreslování. Tokeny se ale neaktualizují, pokud se uživatel ověří po navázání okruhu, protože se HttpContext zachytí na začátku SignalR připojení. Také použití AsyncLocal<T> ze strany IHttpContextAccessor znamená, že musíte být opatrní, abyste neztratili kontext provádění před čtením HttpContext. Další informace najdete v tématu IHttpContextAccessor/HttpContext v aplikacích ASP.NET CoreBlazor.
Ve třídě služby získejte přístup k členům jmenného prostoru Microsoft.AspNetCore.Authentication k zpřístupnění metody GetTokenAsync na HttpContext. Alternativním přístupem, který je okomentovaný v následujícím příkladu, je volat AuthenticateAsync na HttpContext. Pro vrácený AuthenticateResult.Properties zavolejte GetTokenValue.
using Microsoft.AspNetCore.Authentication;
public class AuthenticationProcessor(IHttpContextAccessor httpContextAccessor)
{
public async Task<string?> GetAccessToken()
{
if (httpContextAccessor.HttpContext is null)
{
throw new Exception("HttpContext not available");
}
// Approach 1: Call 'GetTokenAsync'
var accessToken = await httpContextAccessor.HttpContext
.GetTokenAsync("access_token");
// Approach 2: Authenticate the user and call 'GetTokenValue'
/*
var authResult = await httpContextAccessor.HttpContext.AuthenticateAsync();
var accessToken = authResult?.Properties?.GetTokenValue("access_token");
*/
return accessToken;
}
}
Služba je zaregistrovaná v souboru projektu Program serveru:
builder.Services.AddScoped<AuthenticationProcessor>();
AuthenticationProcessor lze vložit do služeb na straně serveru, například do DelegatingHandler pro předkonfigurovaný HttpClient. Následující příklad je určen pouze pro demonstrační účely nebo v případě, že potřebujete provést speciální zpracování ve AuthenticationProcessor službě, protože můžete jednoduše vložit IHttpContextAccessor a získat token přímo pro volání externích webových rozhraní API (další informace o použití IHttpContextAccessor přímo k volání webových rozhraní API naleznete v části Použití obslužné rutiny tokenů pro volání webového rozhraní API ).
using System.Net.Http.Headers;
public class TokenHandler(AuthenticationProcessor authProcessor) :
DelegatingHandler
{
protected override async Task<HttpResponseMessage> SendAsync(
HttpRequestMessage request, CancellationToken cancellationToken)
{
var accessToken = authProcessor.GetAccessToken();
request.Headers.Authorization =
new AuthenticationHeaderValue("Bearer", accessToken);
return await base.SendAsync(request, cancellationToken);
}
}
Obslužná rutina tokenu je zaregistrovaná a funguje jako delegující obslužná rutina pro pojmenovaného klienta HTTP v Program souboru:
builder.Services.AddHttpContextAccessor();
builder.Services.AddScoped<TokenHandler>();
builder.Services.AddHttpClient("ExternalApi",
client => client.BaseAddress = new Uri(builder.Configuration["ExternalApiUri"] ??
throw new Exception("Missing base address!")))
.AddHttpMessageHandler<TokenHandler>();
Upozornění
Ujistěte se, že tokeny nejsou nikdy přenášeny a zpracovávány klientem (.Client projekt), například v komponentě, která přijímá interaktivní automatické zobrazení a je zobrazována na klientovi nebo službě na straně klienta. Vždy požádejte klienta, aby volal server (projekt) pro zpracování požadavků pomocí tokenů.
Tokeny a další ověřovací data by nikdy neměly opustit server.
Informace o interaktivních automatických komponentách najdete v tématu ASP.NET Blazor Ověřování a autorizace jádra, který ukazuje, jak na serveru ponechat přístupové tokeny a další vlastnosti ověřování. Zvažte také přijetí vzoru Backend-for-Frontend (BFF), který přijímá podobnou strukturu volání a je popsán v Zabezpečení ASP.NET Core Blazor Web App s OpenID Connect (OIDC) pro poskytovatele OIDC a Zabezpečení ASP.NET Core Blazor Web App s Microsoft Entra ID pro Microsoft Identity web s Entra.
Použijte zpracovač tokenu pro volání webového rozhraní API
Následující přístup je zaměřený na připojení přístupového tokenu uživatele k odchozím požadavkům, konkrétně k volání webového rozhraní API do externích webových aplikací API. Tento přístup je ukázán pro Blazor Web App, který přijímá globální vykreslování interaktivního serveru, ale stejný obecný přístup platí i pro Blazor Web App globální režim interaktivního automatického vykreslování. Důležitým konceptem, který je potřeba mít na paměti, je, že přístup k HttpContext pomocí IHttpContextAccessor se provádí pouze na serveru.
Ukázku pokynů v této části najdete v aplikacích BlazorWebAppOidc a BlazorWebAppOidcServer (.NET 8 nebo novější) v Blazor ukázkovém úložišti GitHubu. Ukázky přijímají globální interaktivní režim vykreslování a ověřování OIDC s Microsoft Entra bez použití balíčků specifických pro Entra. Ukázky ukazují, jak předat přístupový token JWT pro volání zabezpečeného webového rozhraní API.
Microsoft identity platform s webovými balíčky Microsoftu Identity pro Microsoft Entra ID poskytuje rozhraní API pro volání webových rozhraní API z Blazor Web Appaplikací s automatickou správou a obnovováním tokenů. Další informace najdete v tématu Zabezpečení ASP.NET Core Blazor Web App pomocí Microsoft Entra ID a BlazorWebAppEntraBlazorWebAppEntraBff ukázkových aplikací (.NET 9 nebo novější) v Blazor úložišti GitHub s ukázkami.
Podtřída DelegatingHandler pro připojení přístupového tokenu uživatele k odchozím požadavkům. Obslužná rutina tokenu se spustí jenom na serveru, takže použití HttpContext je bezpečné.
TokenHandler.cs:
using System.Net.Http.Headers;
using Microsoft.AspNetCore.Authentication;
public class TokenHandler(IHttpContextAccessor httpContextAccessor) :
DelegatingHandler
{
protected override async Task<HttpResponseMessage> SendAsync(
HttpRequestMessage request, CancellationToken cancellationToken)
{
if (httpContextAccessor.HttpContext is null)
{
throw new Exception("HttpContext not available");
}
var accessToken = await httpContextAccessor.HttpContext.GetTokenAsync("access_token");
if (accessToken is null)
{
throw new Exception("No access token");
}
request.Headers.Authorization =
new AuthenticationHeaderValue("Bearer", accessToken);
return await base.SendAsync(request, cancellationToken);
}
}
Poznámka:
Pokyny, jak přistoupit k AuthenticationStateProvider z DelegatingHandler, najdete v části Přístup k AuthenticationStateProvider v middleware pro odchozí požadavky.
V souboru projektu Program je obslužná rutina tokenu (TokenHandler) registrována jako vymezená služba a určena jako obslužná rutina zpráv pojmenovaného klienta HTTP s AddHttpMessageHandler.
V následujícím příkladu je zástupný symbol {HTTP CLIENT NAME} názvem HttpClient, a zástupný symbol {BASE ADDRESS} je identifikátor URI základní adresy webového rozhraní API. Další informace o AddHttpContextAccessoraplikaci IHttpContextAccessor/HttpContext najdete v aplikacích ASP.NET CoreBlazor.
V Program.cs:
builder.Services.AddHttpContextAccessor();
builder.Services.AddScoped<TokenHandler>();
builder.Services.AddHttpClient("{HTTP CLIENT NAME}",
client => client.BaseAddress = new Uri("{BASE ADDRESS}"))
.AddHttpMessageHandler<TokenHandler>();
Příklad:
builder.Services.AddScoped<TokenHandler>();
builder.Services.AddHttpClient("ExternalApi",
client => client.BaseAddress = new Uri("https://localhost:7277"))
.AddHttpMessageHandler<TokenHandler>();
Základní adresu klienta HTTP můžete zadat z konfigurace pomocí zástupného symbolu builder.Configuration["{CONFIGURATION KEY}"], kde builder.Configuration["{CONFIGURATION KEY}"] je klíč konfigurace.
new Uri(builder.Configuration["ExternalApiUri"] ?? throw new IOException("No URI!"))
"V appsettings.json určete ExternalApiUri." Následující příklad nastaví hodnotu na adresu localhost externího webového rozhraní API na https://localhost:7277:
"ExternalApiUri": "https://localhost:7277"
V tuto chvíli může komponenta HttpClient vytvořená komponentou provádět zabezpečené požadavky webového rozhraní API. V následujícím příkladu je {REQUEST URI} identifikátor URI relativního požadavku a zástupný symbol {HTTP CLIENT NAME} je název HttpClient.
using var request = new HttpRequestMessage(HttpMethod.Get, "{REQUEST URI}");
var client = ClientFactory.CreateClient("{HTTP CLIENT NAME}");
using var response = await client.SendAsync(request);
Příklad:
using var request = new HttpRequestMessage(HttpMethod.Get, "/weather-forecast");
var client = ClientFactory.CreateClient("ExternalApi");
using var response = await client.SendAsync(request);
Plánují se další funkce pro Blazor, které přístup AuthenticationStateProvider sleduje v middlewaru pro odchozí požadavky (dotnet/aspnetcore #52379).
Problém s poskytováním přístupového tokenu pro HttpClient v interaktivním režimu serveru (dotnet/aspnetcore #52390) je uzavřený problém, který obsahuje užitečnou diskuzi a potenciální strategie alternativního řešení pro pokročilé případy použití.
Tokeny dostupné mimo Razor komponenty v aplikaci na straně Blazor serveru je možné předat komponentám pomocí přístupu popsaného v této části. Příklad v této části se zaměřuje na předávání tokenů XSRF (access, refresh a Blazor ale přístup je platný pro jiný stav kontextu HTTP.
Poznámka:
Předání tokenu Razor XSRF komponentám je užitečné ve scénářích, kdy komponenty POST do Identity nebo jiných koncových bodů, které vyžadují ověření. Pokud vaše aplikace vyžaduje pouze přístup a obnovovací tokeny, můžete z následujícího příkladu odebrat kód tokenu XSRF.
Ověřte aplikaci stejně jako u běžné Razor aplikace Pages nebo MVC. Zřiďte a uložte tokeny do ověřování cookie.
V souboru Program:
using Microsoft.AspNetCore.Authentication.OpenIdConnect;
using Microsoft.IdentityModel.Protocols.OpenIdConnect;
...
builder.Services.Configure<OpenIdConnectOptions>(
OpenIdConnectDefaults.AuthenticationScheme, options =>
{
options.ResponseType = OpenIdConnectResponseType.Code;
options.SaveTokens = true;
options.Scope.Add(OpenIdConnectScope.OfflineAccess);
});
V Startup.cs:
using Microsoft.AspNetCore.Authentication.OpenIdConnect;
using Microsoft.IdentityModel.Protocols.OpenIdConnect;
...
services.Configure<OpenIdConnectOptions>(
OpenIdConnectDefaults.AuthenticationScheme, options =>
{
options.ResponseType = OpenIdConnectResponseType.Code;
options.SaveTokens = true;
options.Scope.Add(OpenIdConnectScope.OfflineAccess);
});
V Startup.cs:
using Microsoft.AspNetCore.Authentication.OpenIdConnect;
using Microsoft.IdentityModel.Protocols.OpenIdConnect;
...
services.Configure<OpenIdConnectOptions>(AzureADDefaults.OpenIdScheme, options =>
{
options.ResponseType = OpenIdConnectResponseType.Code;
options.SaveTokens = true;
options.Scope.Add(OpenIdConnectScope.OfflineAccess);
});
Volitelně jsou přidány další obory s options.Scope.Add("{SCOPE}");, kde {SCOPE} zástupný symbol je další obor, který chcete přidat.
Definujte službu zprostředkovatele tokenů s vymezeným oborem, kterou lze použít v aplikaci Blazor k vyřešení tokenů z vkládání závislostí (DI).
TokenProvider.cs:
public class TokenProvider
{
public string? AccessToken { get; set; }
public string? RefreshToken { get; set; }
public string? XsrfToken { get; set; }
}
Program V souboru přidejte služby pro:
-
IHttpClientFactory: Používá se
WeatherForecastServiceve třídě, která získává data o počasí z rozhraní API serveru s přístupovým tokenem. -
TokenProvider: Uchovává přístupové a obnovovací tokeny.
builder.Services.AddHttpClient();
builder.Services.AddScoped<TokenProvider>();
V Startup.ConfigureServices z Startup.cs přidejte služby pro:
-
IHttpClientFactory: Používá se
WeatherForecastServiceve třídě, která získává data o počasí z rozhraní API serveru s přístupovým tokenem. -
TokenProvider: Uchovává přístupové a obnovovací tokeny.
services.AddHttpClient();
services.AddScoped<TokenProvider>();
Definujte třídu pro předání počátečního stavu aplikace pomocí přístupových a obnovovacích tokenů.
InitialApplicationState.cs:
public class InitialApplicationState
{
public string? AccessToken { get; set; }
public string? RefreshToken { get; set; }
public string? XsrfToken { get; set; }
}
Pages/_Host.cshtml V souboru vytvořte a InitialApplicationState předejte ji jako parametr aplikaci:
Pages/_Layout.cshtml V souboru vytvořte a InitialApplicationState předejte ji jako parametr aplikaci:
Pages/_Host.cshtml V souboru vytvořte a InitialApplicationState předejte ji jako parametr aplikaci:
@using Microsoft.AspNetCore.Authentication
@inject Microsoft.AspNetCore.Antiforgery.IAntiforgery Xsrf
...
@{
var tokens = new InitialApplicationState
{
AccessToken = await HttpContext.GetTokenAsync("access_token"),
RefreshToken = await HttpContext.GetTokenAsync("refresh_token"),
XsrfToken = Xsrf.GetAndStoreTokens(HttpContext).RequestToken
};
}
<component ... param-InitialState="tokens" ... />
V komponentě App (App.razor) přeložte službu a inicializujete ji daty z parametru:
@inject TokenProvider TokenProvider
...
@code {
[Parameter]
public InitialApplicationState? InitialState { get; set; }
protected override Task OnInitializedAsync()
{
TokenProvider.AccessToken = InitialState?.AccessToken;
TokenProvider.RefreshToken = InitialState?.RefreshToken;
TokenProvider.XsrfToken = InitialState?.XsrfToken;
return base.OnInitializedAsync();
}
}
Poznámka:
Alternativou k přiřazení počátečního stavu k TokenProvider předchozímu příkladu je zkopírování dat do služby s vymezeným oborem pro OnInitializedAsync použití v rámci aplikace.
Přidejte do aplikace Microsoft.AspNet.WebApi.Client odkaz na balíček NuGet.
Poznámka:
Pokyny k přidávání balíčků do aplikací .NET najdete v článcích o instalaci a správě balíčků v pracovním postupu Používání balíčků (dokumentace NuGet). Ověřte správné verze balíčků v NuGet.org.
Ve službě, která vytvoří požadavek na zabezpečené rozhraní API, vkněte zprostředkovatele tokenu a načtěte token pro požadavek rozhraní API:
WeatherForecastService.cs:
using System;
using System.Net.Http;
using System.Threading.Tasks;
public class WeatherForecastService
{
private readonly HttpClient http;
private readonly TokenProvider tokenProvider;
public WeatherForecastService(IHttpClientFactory clientFactory,
TokenProvider tokenProvider)
{
http = clientFactory.CreateClient();
this.tokenProvider = tokenProvider;
}
public async Task<WeatherForecast[]> GetForecastAsync()
{
var token = tokenProvider.AccessToken;
using var request = new HttpRequestMessage(HttpMethod.Get,
"https://localhost:5003/WeatherForecast");
request.Headers.Add("Authorization", $"Bearer {token}");
using var response = await http.SendAsync(request);
response.EnsureSuccessStatusCode();
return await response.Content.ReadFromJsonAsync<WeatherForecast[]>() ??
Array.Empty<WeatherForecast>();
}
}
V případě tokenu XSRF předaného komponentě vložte TokenProvider token XSRF a přidejte ho do požadavku POST. Následující příklad přidá token do koncového bodu odhlášení POST. Scénář pro následující příklad je, že koncový bod odhlášení (Areas/Identity/Pages/Account/Logout.cshtmlvytvořený jako součást aplikace) neuvádí IgnoreAntiforgeryTokenAttribute (@attribute [IgnoreAntiforgeryToken]), protože provádí nějakou akci kromě běžného odhlášení, které musí být chráněno. Koncový bod vyžaduje k úspěšnému zpracování požadavku platný token XSRF.
V komponentě, která představuje tlačítko odhlášení autorizovaným uživatelům:
@inject TokenProvider TokenProvider
...
<AuthorizeView>
<Authorized>
<form action="/Identity/Account/Logout?returnUrl=%2F" method="post">
<button class="nav-link btn btn-link" type="submit">Logout</button>
<input name="__RequestVerificationToken" type="hidden"
value="@TokenProvider.XsrfToken">
</form>
</Authorized>
<NotAuthorized>
...
</NotAuthorized>
</AuthorizeView>
Nastavení schématu ověřování
Pro aplikaci, která používá více než jeden middleware ověřování a má tedy více než jedno schéma ověřování, lze schéma, které Blazor používá, explicitně nastavit v konfiguraci koncového Program bodu souboru. Následující příklad nastaví schéma OpenID Connect (OIDC):
Pro aplikaci, která používá více než jeden middleware ověřování, a proto má více než jedno schéma ověřování, schéma, které Blazor se používá, lze explicitně nastavit v konfiguraci koncového Startup.csbodu . Následující příklad nastaví schéma OpenID Connect (OIDC):
using Microsoft.AspNetCore.Authentication.OpenIdConnect;
...
app.MapRazorComponents<App>().RequireAuthorization(
new AuthorizeAttribute
{
AuthenticationSchemes = OpenIdConnectDefaults.AuthenticationScheme
})
.AddInteractiveServerRenderMode();
using Microsoft.AspNetCore.Authentication.OpenIdConnect;
...
app.MapBlazorHub().RequireAuthorization(
new AuthorizeAttribute
{
AuthenticationSchemes = OpenIdConnectDefaults.AuthenticationScheme
});
Pro aplikaci, která používá více než jeden middleware ověřování, a proto má více než jedno schéma ověřování, schéma, které Blazor se používá, lze explicitně nastavit v konfiguraci koncového Startup.Configurebodu . Následující příklad nastaví schéma MICROSOFT Entra ID:
endpoints.MapBlazorHub().RequireAuthorization(
new AuthorizeAttribute
{
AuthenticationSchemes = AzureADDefaults.AuthenticationScheme
});
Použití koncových bodů OpenID Connect (OIDC) v2.0
Ve verzích ASP.NET Core před verzí .NET 5 knihovna pro ověřování a šablony Blazor používají koncové body OpenID Connect (OIDC) v1.0. Pokud chcete použít koncový bod verze 2.0 s verzemi ASP.NET Core staršími než .NET 5, nakonfigurujte možnost OpenIdConnectOptions.Authority v OpenIdConnectOptions.
services.Configure<OpenIdConnectOptions>(AzureADDefaults.OpenIdScheme,
options =>
{
options.Authority += "/v2.0";
}
Případně můžete nastavení provést v souboru nastavení aplikace (appsettings.json):
{
"AzureAd": {
"Authority": "https://login.microsoftonline.com/common/oauth2/v2.0",
...
}
}
Pokud přiřakání segmentu autoritě není vhodné pro poskytovatele OIDC aplikace, například u jiných poskytovatelů než ME-ID, nastavte Authority vlastnost přímo. Buď nastavte vlastnost v OpenIdConnectOptions souboru nastavení aplikace nebo v klíči Authority .
Změny kódu
Seznam deklarací identity v tokenu ID se změní pro koncové body v2.0. Dokumentace Microsoftu ke změnám byla vyřazena, ale pokyny k deklaracím identity v tokenu ID jsou k dispozici v referenčních informacích k deklaracím tokenů ID.
Vzhledem k tomu, že prostředky jsou zadané v identifikátorech URI oboru pro koncové body v2.0, odeberte OpenIdConnectOptions.Resource nastavení vlastnosti v OpenIdConnectOptions:
services.Configure<OpenIdConnectOptions>(AzureADDefaults.OpenIdScheme, options => { ... options.Resource = "..."; // REMOVE THIS LINE ... }
Identifikátor URI ID aplikace
- Při použití koncových bodů v2.0 rozhraní API definují
App ID URIrozhraní API , která má představovat jedinečný identifikátor rozhraní API. - Všechny obory zahrnují identifikátor URI ID aplikace jako předponu a koncové body verze 2.0 generují přístupové tokeny s identifikátorem URI ID aplikace jako cílovou skupinou.
- Při použití koncových bodů V2.0 se ID klienta nakonfigurované v rozhraní API serveru změní z ID aplikace rozhraní API (ID klienta) na identifikátor URI ID aplikace aplikace.
appsettings.json:
{
"AzureAd": {
...
"ClientId": "https://{TENANT}.onmicrosoft.com/{PROJECT NAME}"
...
}
}
Identifikátor URI ID aplikace, který se má použít, najdete v popisu registrace aplikace poskytovatele OIDC.
Obslužná rutina okruhu pro zachycení uživatelů pro vlastní služby
CircuitHandler Použijte k zachycení uživatele ze AuthenticationStateProvider služby a nastavení uživatele ve službě. Pokud chcete aktualizovat uživatele, zaregistrujte zpětná volání a AuthenticationStateChangedTask vytvořte frontu, abyste získali nového uživatele a aktualizovali službu. Následující příklad ukazuje přístup.
V následujícím příkladu:
-
OnConnectionUpAsync se volá při každém opětovném připojení okruhu a nastavení uživatele po dobu životnosti připojení.
OnConnectionUpAsync Pouze metoda se vyžaduje, pokud neimplementujete aktualizace prostřednictvím obslužné rutiny pro změny ověřování (
AuthenticationChangedv následujícím příkladu). -
OnCircuitOpenedAsync je volána pro připojení ověřovací změněné obslužné rutiny ,
AuthenticationChangedaktualizovat uživatele. - Blok
catchUpdateAuthenticationúlohy nemá žádnou akci na výjimky, protože neexistuje způsob, jak v tomto okamžiku při provádění kódu nahlásit výjimky. Pokud je z úlohy vyvoláná výjimka, je výjimka hlášena jinde v aplikaci.
UserService.cs:
using System.Security.Claims;
using Microsoft.AspNetCore.Components.Authorization;
using Microsoft.AspNetCore.Components.Server.Circuits;
public class UserService
{
private ClaimsPrincipal currentUser = new(new ClaimsIdentity());
public ClaimsPrincipal GetUser() => currentUser;
internal void SetUser(ClaimsPrincipal user)
{
if (currentUser != user)
{
currentUser = user;
}
}
}
internal sealed class UserCircuitHandler(
AuthenticationStateProvider authenticationStateProvider,
UserService userService)
: CircuitHandler, IDisposable
{
public override Task OnCircuitOpenedAsync(Circuit circuit,
CancellationToken cancellationToken)
{
authenticationStateProvider.AuthenticationStateChanged +=
AuthenticationChanged;
return base.OnCircuitOpenedAsync(circuit, cancellationToken);
}
private void AuthenticationChanged(Task<AuthenticationState> task)
{
_ = UpdateAuthentication(task);
async Task UpdateAuthentication(Task<AuthenticationState> task)
{
try
{
var state = await task;
userService.SetUser(state.User);
}
catch
{
}
}
}
public override async Task OnConnectionUpAsync(Circuit circuit,
CancellationToken cancellationToken)
{
var state = await authenticationStateProvider.GetAuthenticationStateAsync();
userService.SetUser(state.User);
}
public void Dispose()
{
authenticationStateProvider.AuthenticationStateChanged -=
AuthenticationChanged;
}
}
using System.Security.Claims;
using Microsoft.AspNetCore.Components.Authorization;
using Microsoft.AspNetCore.Components.Server.Circuits;
public class UserService
{
private ClaimsPrincipal currentUser = new ClaimsPrincipal(new ClaimsIdentity());
public ClaimsPrincipal GetUser()
{
return currentUser;
}
internal void SetUser(ClaimsPrincipal user)
{
if (currentUser != user)
{
currentUser = user;
}
}
}
internal sealed class UserCircuitHandler : CircuitHandler, IDisposable
{
private readonly AuthenticationStateProvider authenticationStateProvider;
private readonly UserService userService;
public UserCircuitHandler(
AuthenticationStateProvider authenticationStateProvider,
UserService userService)
{
this.authenticationStateProvider = authenticationStateProvider;
this.userService = userService;
}
public override Task OnCircuitOpenedAsync(Circuit circuit,
CancellationToken cancellationToken)
{
authenticationStateProvider.AuthenticationStateChanged +=
AuthenticationChanged;
return base.OnCircuitOpenedAsync(circuit, cancellationToken);
}
private void AuthenticationChanged(Task<AuthenticationState> task)
{
_ = UpdateAuthentication(task);
async Task UpdateAuthentication(Task<AuthenticationState> task)
{
try
{
var state = await task;
userService.SetUser(state.User);
}
catch
{
}
}
}
public override async Task OnConnectionUpAsync(Circuit circuit,
CancellationToken cancellationToken)
{
var state = await authenticationStateProvider.GetAuthenticationStateAsync();
userService.SetUser(state.User);
}
public void Dispose()
{
authenticationStateProvider.AuthenticationStateChanged -=
AuthenticationChanged;
}
}
V souboru Program:
using Microsoft.AspNetCore.Components.Server.Circuits;
using Microsoft.Extensions.DependencyInjection.Extensions;
...
builder.Services.AddScoped<UserService>();
builder.Services.TryAddEnumerable(
ServiceDescriptor.Scoped<CircuitHandler, UserCircuitHandler>());
V Startup.ConfigureServices z Startup.cs:
using Microsoft.AspNetCore.Components.Server.Circuits;
using Microsoft.Extensions.DependencyInjection.Extensions;
...
services.AddScoped<UserService>();
services.TryAddEnumerable(
ServiceDescriptor.Scoped<CircuitHandler, UserCircuitHandler>());
Pomocí služby v komponentě získejte uživatele:
@inject UserService UserService
<h1>Hello, @(UserService.GetUser().Identity?.Name ?? "world")!</h1>
Pokud chcete nastavit uživatele v middlewaru pro MVC, Razor Pages a v jiných scénářích ASP.NET Core, zavolejte SetUserUserService ve vlastním middlewaru po spuštění middlewaru ověřování nebo nastavte uživatele s implementací IClaimsTransformation . Následující příklad přijímá přístup middlewaru.
UserServiceMiddleware.cs:
public class UserServiceMiddleware
{
private readonly RequestDelegate next;
public UserServiceMiddleware(RequestDelegate next)
{
this.next = next ?? throw new ArgumentNullException(nameof(next));
}
public async Task InvokeAsync(HttpContext context, UserService service)
{
service.SetUser(context.User);
await next(context);
}
}
Bezprostředně před voláním app.MapRazorComponents<App>() do Program souboru zavolejte middleware:
Bezprostředně před voláním app.MapBlazorHub() do Program souboru zavolejte middleware:
Bezprostředně před voláním app.MapBlazorHub()Startup.ConfigureStartup.csdo , zavolejte middleware:
app.UseMiddleware<UserServiceMiddleware>();
Přístup AuthenticationStateProvider k middlewaru odchozích požadavků
Do middlewaru při odchozích požadavcích z AuthenticationStateProvider vytvořeného pomocí DelegatingHandler lze přistupovat pomocí obslužného programu HttpClient.
Poznámka:
Obecné pokyny k definování delegujících obslužných rutin pro požadavky HTTP pomocí instancí vytvořených HttpClient pomocí IHttpClientFactory v aplikacích ASP.NET Core najdete v následujících částech Vytváření požadavků HTTP pomocí IHttpClientFactory v ASP.NET Core:
Následující příklad používá AuthenticationStateProvider k připojení vlastní hlavičky uživatelského jména pro ověřené uživatele k odchozím požadavkům.
Nejprve implementujte CircuitServicesAccessor třídu v následující části Blazor článku injektáž závislostí (DI):
Přistupte ke službám na straně Blazor serveru z jiného DI kontextu
CircuitServicesAccessor Použijte k přístupu k implementaci AuthenticationStateProviderDelegatingHandler.
AuthenticationStateHandler.cs:
using Microsoft.AspNetCore.Components.Authorization;
public class AuthenticationStateHandler(
CircuitServicesAccessor circuitServicesAccessor)
: DelegatingHandler
{
protected override async Task<HttpResponseMessage> SendAsync(
HttpRequestMessage request, CancellationToken cancellationToken)
{
var authStateProvider = circuitServicesAccessor.Services?
.GetRequiredService<AuthenticationStateProvider>();
if (authStateProvider is null)
{
throw new Exception("AuthenticationStateProvider not available");
}
var authState = await authStateProvider.GetAuthenticationStateAsync();
var user = authState?.User;
if (user?.Identity is not null && user.Identity.IsAuthenticated)
{
request.Headers.Add("X-USER-IDENTITY-NAME", user.Identity.Name);
}
return await base.SendAsync(request, cancellationToken);
}
}
Program V souboru zaregistrujte AuthenticationStateHandler a přidejte obslužnou rutinu do IHttpClientFactory instance, která vytváří HttpClient instance:
builder.Services.AddTransient<AuthenticationStateHandler>();
builder.Services.AddHttpClient("HttpMessageHandler")
.AddHttpMessageHandler<AuthenticationStateHandler>();