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.
Note
Toto není nejnovější verze tohoto článku. Aktuální verzi najdete ve verzi .NET 10 tohoto článku.
Warning
Tato verze ASP.NET Core se už nepodporuje. Další informace najdete v zásadách podpory .NET a .NET Core. Aktuální verzi tohoto článku naleznete ve verzi .NET 9.
Tento článek popisuje další scénáře zabezpečení pro Blazor WebAssembly aplikace.
Připojení tokenů k odchozím požadavkům
AuthorizationMessageHandler je to DelegatingHandler, který slouží ke zpracování přístupových tokenů. Tokeny se získávají pomocí IAccessTokenProvider služby, která je zaregistrovaná architekturou. Pokud se token nedá získat, vyvolá se chyba AccessTokenNotAvailableException . AccessTokenNotAvailableException má metodu Redirect , která pomocí AccessTokenResult.InteractiveRequestUrl dané metody AccessTokenResult.InteractionOptions povolí aktualizaci přístupového tokenu.
Pro usnadnění přístupu poskytuje BaseAddressAuthorizationMessageHandler architektura předkonfigurovanou základní adresu aplikace jako autorizovanou adresu URL. Přístupové tokeny se přidají jenom v případech, kdy je identifikátor URI požadavku v rámci základního identifikátoru URI aplikace. Pokud URI odchozích požadavků nejsou v základním identifikátoru URI aplikace, použijte vlastní AuthorizationMessageHandler třídu (doporučeno) nebo nakonfigurujte AuthorizationMessageHandler.
Note
Kromě konfigurace klientské aplikace pro přístup k rozhraní API serveru musí rozhraní API serveru také povolit požadavky mezi zdroji (CORS), pokud se klient a server nenachází na stejnou základní adresu. Další informace o konfiguraci CORS na straně serveru najdete v části Sdílení prostředků mezi zdroji (CORS) dále v tomto článku.
V následujícím příkladu:
-
AddHttpClient přidá IHttpClientFactory do kolekce služeb související služby a nakonfiguruje pojmenovanou HttpClient (
WebAPI). HttpClient.BaseAddress je základní adresa identifikátoru URI prostředku při odesílání požadavků. IHttpClientFactory je poskytován balíčkem NuGetMicrosoft.Extensions.Http. - BaseAddressAuthorizationMessageHandler DelegatingHandler slouží ke zpracování přístupových tokenů. Přístupové tokeny se přidají jenom v případech, kdy je identifikátor URI požadavku v rámci základního identifikátoru URI aplikace.
-
IHttpClientFactory.CreateClient vytvoří a nakonfiguruje HttpClient instanci pro odchozí požadavky pomocí konfigurace, která odpovídá pojmenované HttpClient (
WebAPI).
V následujícím příkladu HttpClientFactoryServiceCollectionExtensions.AddHttpClient je rozšíření v Microsoft.Extensions.Http. Přidejte balíček do aplikace, která na něj ještě neodkazuje.
Note
Pokyny k přidávání balíčků do aplikací .NET najdete v článcích v části Instalace a správa balíčků na webu Pracovní postup používání balíčků (dokumentace k NuGetu). Ověřte správné verze balíčků na NuGet.org.
using System.Net.Http;
using Microsoft.AspNetCore.Components.WebAssembly.Authentication;
...
builder.Services.AddHttpClient("WebAPI",
client => client.BaseAddress = new Uri("https://api.contoso.com/v1.0"))
.AddHttpMessageHandler<BaseAddressAuthorizationMessageHandler>();
builder.Services.AddScoped(sp => sp.GetRequiredService<IHttpClientFactory>()
.CreateClient("WebAPI"));
U hostovaného Blazorřešení založeného na šabloně Blazor WebAssembly projektu jsou URI požadavků v rámci základního URI aplikace. Proto je IWebAssemblyHostEnvironment.BaseAddress (new Uri(builder.HostEnvironment.BaseAddress)) přiřazen k HttpClient.BaseAddress v aplikaci vygenerované ze šablony projektu.
Nakonfigurované HttpClient se používá k provádění autorizovaných try-catch požadavků pomocí vzoru:
@using Microsoft.AspNetCore.Components.WebAssembly.Authentication
@inject HttpClient Http
...
protected override async Task OnInitializedAsync()
{
try
{
var examples =
await Http.GetFromJsonAsync<ExampleType[]>("ExampleAPIMethod");
...
}
catch (AccessTokenNotAvailableException exception)
{
exception.Redirect();
}
}
Scénáře požadavků na vlastní ověřování
Následující scénáře ukazují, jak přizpůsobit žádosti o ověření a jak získat cestu přihlášení z možností ověřování.
Přizpůsobení procesu přihlášení
Spravujte další parametry pro žádost o přihlášení pomocí následujících metod jednou nebo vícekrát v nové instanci InteractiveRequestOptions:
V následujícím LoginDisplay příkladu komponenty se do žádosti o přihlášení přidají další parametry:
-
promptje nastavena naloginhodnotu : Vynutí, aby uživatel zadal své přihlašovací údaje pro danou žádost a neguje jednotné přihlašování. -
loginHintje nastavena napeter@contoso.com: Předvyplní pole uživatelské jméno/e-mailová adresa na přihlašovací stránce pro uživatele napeter@contoso.com. Aplikace tento parametr často používají při opětovném ověřování, přičemž uživatelské jméno již bylo extrahováno z předchozího přihlášení pomocí nárokupreferred_username.
Shared/LoginDisplay.razor:
@using Microsoft.AspNetCore.Components.Authorization
@using Microsoft.AspNetCore.Components.WebAssembly.Authentication
@inject NavigationManager Navigation
<AuthorizeView>
<Authorized>
Hello, @context.User.Identity?.Name!
<button @onclick="BeginLogOut">Log out</button>
</Authorized>
<NotAuthorized>
<button @onclick="BeginLogIn">Log in</button>
</NotAuthorized>
</AuthorizeView>
@code{
public void BeginLogOut()
{
Navigation.NavigateToLogout("authentication/logout");
}
public void BeginLogIn()
{
InteractiveRequestOptions requestOptions =
new()
{
Interaction = InteractionType.SignIn,
ReturnUrl = Navigation.Uri,
};
requestOptions.TryAddAdditionalParameter("prompt", "login");
requestOptions.TryAddAdditionalParameter("loginHint", "peter@contoso.com");
Navigation.NavigateToLogin("authentication/login", requestOptions);
}
}
Další informace naleznete v následujících zdrojích:
Přizpůsobení možností před interaktivním získáním tokenu
Pokud dojde k AccessTokenNotAvailableException, spravujte další parametry pro požadavek nového přístupového tokenu zprostředkovatele identity pomocí následujících metod jednou nebo vícekrát v nové instanci InteractiveRequestOptions.
V následujícím příkladu, který získává data JSON prostřednictvím webového rozhraní API, se do požadavku přesměrování přidají další parametry, pokud přístupový token není k dispozici (AccessTokenNotAvailableException vyvolá se):
-
promptje nastavena naloginhodnotu : Vynutí, aby uživatel zadal své přihlašovací údaje pro danou žádost a neguje jednotné přihlašování. -
loginHintje nastavena napeter@contoso.com: Předvyplní pole uživatelské jméno/e-mailová adresa na přihlašovací stránce pro uživatele napeter@contoso.com. Aplikace tento parametr často používají při opětovném ověřování, přičemž uživatelské jméno již bylo extrahováno z předchozího přihlášení pomocí nárokupreferred_username.
try
{
var examples = await Http.GetFromJsonAsync<ExampleType[]>("ExampleAPIMethod");
...
}
catch (AccessTokenNotAvailableException ex)
{
ex.Redirect(requestOptions => {
requestOptions.TryAddAdditionalParameter("prompt", "login");
requestOptions.TryAddAdditionalParameter("loginHint", "peter@contoso.com");
});
}
Předchozí příklad předpokládá, že:
- Přítomnost příkazu
@using/usingpro rozhraní API v Microsoft.AspNetCore.Components.WebAssembly.Authentication oboru názvů -
HttpClientinjekčně jakoHttp.
Další informace naleznete v následujících zdrojích:
Přizpůsobení možností při použití IAccessTokenProvider
Pokud se při použití IAccessTokenProvidernepodaří získat token, spravujte další parametry pro žádost o nový přístupový token poskytovatele identity jednou nebo vícekrát na nové instanci InteractiveRequestOptions.
V následujícím příkladu, který se pokusí získat přístupový token pro uživatele, se do žádosti o přihlášení přidají další parametry, pokud se při volání pokusu o získání tokenu nezdaří TryGetToken :
-
promptje nastavena naloginhodnotu : Vynutí, aby uživatel zadal své přihlašovací údaje pro danou žádost a neguje jednotné přihlašování. -
loginHintje nastavena napeter@contoso.com: Předvyplní pole uživatelské jméno/e-mailová adresa na přihlašovací stránce pro uživatele napeter@contoso.com. Aplikace tento parametr často používají při opětovném ověřování, přičemž uživatelské jméno již bylo extrahováno z předchozího přihlášení pomocí nárokupreferred_username.
var tokenResult = await TokenProvider.RequestAccessToken(
new AccessTokenRequestOptions
{
Scopes = [ ... ]
});
if (!tokenResult.TryGetToken(out var token))
{
tokenResult.InteractionOptions.TryAddAdditionalParameter("prompt", "login");
tokenResult.InteractionOptions.TryAddAdditionalParameter("loginHint",
"peter@contoso.com");
Navigation.NavigateToLogin(accessTokenResult.InteractiveRequestUrl,
accessTokenResult.InteractionOptions);
}
var tokenResult = await TokenProvider.RequestAccessToken(
new AccessTokenRequestOptions
{
Scopes = new[] { ... }
});
if (!tokenResult.TryGetToken(out var token))
{
tokenResult.InteractionOptions.TryAddAdditionalParameter("prompt", "login");
tokenResult.InteractionOptions.TryAddAdditionalParameter("loginHint",
"peter@contoso.com");
Navigation.NavigateToLogin(accessTokenResult.InteractiveRequestUrl,
accessTokenResult.InteractionOptions);
}
Předchozí příklad předpokládá:
- Přítomnost příkazu
@using/usingpro rozhraní API v Microsoft.AspNetCore.Components.WebAssembly.Authentication oboru názvů -
IAccessTokenProvider injekčně jako
TokenProvider.
Další informace naleznete v následujících zdrojích:
Odhlášení s vlastní návratovou adresou URL
Následující příklad odhlásí uživatele a vrátí uživatele do koncového /goodbye bodu:
Navigation.NavigateToLogout("authentication/logout", "goodbye");
Získat přihlašovací cestu z možností ověřování
Získejte nakonfigurovanou přihlašovací cestu z RemoteAuthenticationOptions:
var loginPath =
RemoteAuthOptions.Get(Options.DefaultName).AuthenticationPaths.LogInPath;
Předchozí příklad předpokládá:
-
@using/usingPřítomnost příkazu pro rozhraní API v následujících oborech názvů: -
IOptionsSnapshot<RemoteAuthenticationOptions<ApiAuthorizationProviderOptions>>injekčně jakoRemoteAuthOptions.
Vlastní AuthorizationMessageHandler třída
Tyto pokyny v této části se doporučují pro klientské aplikace, které odesílají odchozí požadavky na identifikátory URI, které nejsou v rámci základního identifikátoru URI aplikace.
V následujícím příkladu se vlastní třída rozšiřuje AuthorizationMessageHandler pro použití jako DelegatingHandler pro HttpClient. ConfigureHandler nakonfiguruje tuto obslužnou rutinu tak, aby autorizovala odchozí požadavky HTTP pomocí přístupového tokenu. Přístupový token je připojen pouze v případě, že alespoň jedna z autorizovaných adres URL je základem identifikátoru URI požadavku (HttpRequestMessage.RequestUri).
using Microsoft.AspNetCore.Components;
using Microsoft.AspNetCore.Components.WebAssembly.Authentication;
public class CustomAuthorizationMessageHandler : AuthorizationMessageHandler
{
public CustomAuthorizationMessageHandler(IAccessTokenProvider provider,
NavigationManager navigation)
: base(provider, navigation)
{
ConfigureHandler(
authorizedUrls: [ "https://api.contoso.com/v1.0" ],
scopes: [ "example.read", "example.write" ]);
}
}
Note
V této části se použije předchozí obslužný program zprávy při vytvoření nakonfigurovaného HttpClient z vloženého IHttpClientFactory. Pokud nepoužíváte IHttpClientFactoryinstanci, musíte vytvořit HttpClientHandler instanci a přiřadit ji k objektu AuthorizationMessageHandler's DelegatingHandler.InnerHandler:
InnerHandler = new HttpClientHandler();
Nemusíte provádět předchozí InnerHandler přiřazení, pokud použijete IHttpClientFactory, protože jak ExampleAPIMethod volání demonstruje později v této části.
V předchozím kódu nejsou obory example.read a example.write obecné příklady, které by odrážely platné obory pro konkrétního poskytovatele.
V souboru Program je CustomAuthorizationMessageHandler registrované jako přechodná služba a konfigurováno jako DelegatingHandler pro odchozí instance HttpResponseMessage vytvořené pojmenovanou HttpClient.
V následujícím příkladu HttpClientFactoryServiceCollectionExtensions.AddHttpClient je rozšíření v Microsoft.Extensions.Http. Přidejte balíček do aplikace, která na něj ještě neodkazuje.
Note
Pokyny k přidávání balíčků do aplikací .NET najdete v článcích v části Instalace a správa balíčků na webu Pracovní postup používání balíčků (dokumentace k NuGetu). Ověřte správné verze balíčků na NuGet.org.
builder.Services.AddTransient<CustomAuthorizationMessageHandler>();
builder.Services.AddHttpClient("WebAPI",
client => client.BaseAddress = new Uri("https://api.contoso.com/v1.0"))
.AddHttpMessageHandler<CustomAuthorizationMessageHandler>();
Note
V předchozím příkladu CustomAuthorizationMessageHandlerDelegatingHandler je registrován jako přechodná služba pro AddHttpMessageHandler. Přechodná registrace se doporučuje pro IHttpClientFactory, která spravuje vlastní obory DI. Další informace naleznete v následujících zdrojích:
Pro hostované Blazor řešení založené na Blazor WebAssembly šabloně projektu je IWebAssemblyHostEnvironment.BaseAddress (new Uri(builder.HostEnvironment.BaseAddress)) přiřazeno k HttpClient.BaseAddress.
Nakonfigurované HttpClient se používá k provádění autorizovaných požadavků pomocí try-catch vzoru. Když je klient vytvořen pomocí CreateClient (Microsoft.Extensions.Http balíčku), jsou poskytnuty instance HttpClient, které při provádění požadavků na serverové rozhraní API obsahují přístupové tokeny. Pokud je identifikátor URI požadavku relativním identifikátorem URI, jako je tomu v následujícím příkladu (ExampleAPIMethod), zkombinuje se s BaseAddress, když klientská aplikace provede požadavek.
@inject IHttpClientFactory ClientFactory
...
@code {
protected override async Task OnInitializedAsync()
{
try
{
var client = ClientFactory.CreateClient("WebAPI");
var examples =
await client.GetFromJsonAsync<ExampleType[]>("ExampleAPIMethod");
...
}
catch (AccessTokenNotAvailableException exception)
{
exception.Redirect();
}
}
}
Konfigurovat AuthorizationMessageHandler
Pomocí metody AuthorizationMessageHandler lze ConfigureHandler nakonfigurovat s autorizovanými adresami URL, rozsahy a návratovou adresou URL. ConfigureHandler nakonfiguruje obslužnou rutinu tak, aby autorizovala odchozí požadavky HTTP pomocí přístupového tokenu. Přístupový token je připojen pouze v případě, že alespoň jedna z autorizovaných adres URL je základem identifikátoru URI požadavku (HttpRequestMessage.RequestUri). Pokud je URI požadavku relativní, zkombinuje se s identifikátorem BaseAddress.
V následujícím příkladu AuthorizationMessageHandlerHttpClient nakonfiguruje souborProgram:
using System.Net.Http;
using Microsoft.AspNetCore.Components.WebAssembly.Authentication;
...
builder.Services.AddScoped(sp => new HttpClient(
sp.GetRequiredService<AuthorizationMessageHandler>()
.ConfigureHandler(
authorizedUrls: [ "https://api.contoso.com/v1.0" ],
scopes: [ "example.read", "example.write" ])
.InnerHandler = new HttpClientHandler())
{
BaseAddress = new Uri("https://api.contoso.com/v1.0")
});
V předchozím kódu:
- Obory
example.readaexample.writejsou obecné příklady, které nemají odrážet platné obory pro konkrétního poskytovatele. - IHttpClientFactory se nepoužívá k vytváření HttpClient instancí, takže HttpClientHandler instance je ručně vytvořena a přiřazena k objektu AuthorizationMessageHandler's DelegatingHandler.InnerHandler.
Pro Blazor hostované řešení založené na Blazor WebAssembly šabloně, je projektu IWebAssemblyHostEnvironment.BaseAddress přiřazeno následující:
-
HttpClient.BaseAddress (
new Uri(builder.HostEnvironment.BaseAddress)). - Adresa URL
authorizedUrlspole.
Psaný na stroji HttpClient
Lze definovat typového klienta, který zpracovává všechny záležitosti týkající se HTTP a získávání tokenů v rámci jedné třídy.
WeatherForecastClient.cs:
using System.Net.Http.Json;
using Microsoft.AspNetCore.Components.WebAssembly.Authentication;
using static {PACKAGE ID/ASSEMBLY NAME}.Data;
public class WeatherForecastClient(HttpClient http)
{
private WeatherForecast[]? forecasts;
public async Task<WeatherForecast[]> GetForecastAsync()
{
try
{
forecasts = await http.GetFromJsonAsync<WeatherForecast[]>(
"WeatherForecast");
}
catch (AccessTokenNotAvailableException exception)
{
exception.Redirect();
}
return forecasts ?? Array.Empty<WeatherForecast>();
}
}
V předchozím příkladu WeatherForecast je typ statickou třídou, která obsahuje data předpovědi počasí. Zástupný {PACKAGE ID/ASSEMBLY NAME} symbol je ID balíčku projektu (<PackageId> v souboru projektu) pro knihovnu nebo název sestavení aplikace (například using static BlazorSample.Data;).
V následujícím příkladu HttpClientFactoryServiceCollectionExtensions.AddHttpClient je rozšíření v Microsoft.Extensions.Http. Přidejte balíček do aplikace, která na něj ještě neodkazuje.
Note
Pokyny k přidávání balíčků do aplikací .NET najdete v článcích v části Instalace a správa balíčků na webu Pracovní postup používání balíčků (dokumentace k NuGetu). Ověřte správné verze balíčků na NuGet.org.
V souboru Program:
using System.Net.Http;
using Microsoft.AspNetCore.Components.WebAssembly.Authentication;
...
builder.Services.AddHttpClient<WeatherForecastClient>(
client => client.BaseAddress = new Uri("https://api.contoso.com/v1.0"))
.AddHttpMessageHandler<BaseAddressAuthorizationMessageHandler>();
Pro hostované Blazor řešení založené na Blazor WebAssembly šabloně projektu je IWebAssemblyHostEnvironment.BaseAddress (new Uri(builder.HostEnvironment.BaseAddress)) přiřazeno k HttpClient.BaseAddress.
V komponentě, která načítá data o počasí:
@inject WeatherForecastClient Client
...
protected override async Task OnInitializedAsync()
{
forecasts = await Client.GetForecastAsync();
}
Nakonfigurujte obslužnou rutinu HttpClient
Obslužnou rutinu je možné nakonfigurovat dále s ConfigureHandler pro odchozí požadavky HTTP.
V následujícím příkladu HttpClientFactoryServiceCollectionExtensions.AddHttpClient je rozšíření v Microsoft.Extensions.Http. Přidejte balíček do aplikace, která na něj ještě neodkazuje.
Note
Pokyny k přidávání balíčků do aplikací .NET najdete v článcích v části Instalace a správa balíčků na webu Pracovní postup používání balíčků (dokumentace k NuGetu). Ověřte správné verze balíčků na NuGet.org.
V souboru Program:
builder.Services.AddHttpClient<WeatherForecastClient>(
client => client.BaseAddress = new Uri("https://api.contoso.com/v1.0"))
.AddHttpMessageHandler(sp => sp.GetRequiredService<AuthorizationMessageHandler>()
.ConfigureHandler(
authorizedUrls: [ "https://api.contoso.com/v1.0" ],
scopes: [ "example.read", "example.write" ]));
builder.Services.AddHttpClient<WeatherForecastClient>(
client => client.BaseAddress = new Uri("https://api.contoso.com/v1.0"))
.AddHttpMessageHandler(sp => sp.GetRequiredService<AuthorizationMessageHandler>()
.ConfigureHandler(
authorizedUrls: new[] { "https://api.contoso.com/v1.0" },
scopes: new[] { "example.read", "example.write" }));
V předchozím kódu nejsou obory example.read a example.write obecné příklady, které by odrážely platné obory pro konkrétního poskytovatele.
Pro Blazor hostované řešení založené na Blazor WebAssembly šabloně, je projektu IWebAssemblyHostEnvironment.BaseAddress přiřazeno následující:
-
HttpClient.BaseAddress (
new Uri(builder.HostEnvironment.BaseAddress)). - Adresa URL
authorizedUrlspole.
Neověřené nebo neoprávněné požadavky webového rozhraní API v aplikaci se zabezpečeným výchozím klientem
Aplikace, která obvykle používá zabezpečené výchozí nastavení HttpClient, může také provádět neověřené nebo neoprávněné požadavky webového rozhraní API konfigurací pojmenovaného HttpClient.
V následujícím příkladu HttpClientFactoryServiceCollectionExtensions.AddHttpClient je rozšíření v Microsoft.Extensions.Http. Přidejte balíček do aplikace, která na něj ještě neodkazuje.
Note
Pokyny k přidávání balíčků do aplikací .NET najdete v článcích v části Instalace a správa balíčků na webu Pracovní postup používání balíčků (dokumentace k NuGetu). Ověřte správné verze balíčků na NuGet.org.
V souboru Program:
builder.Services.AddHttpClient("WebAPI.NoAuthenticationClient",
client => client.BaseAddress = new Uri("https://api.contoso.com/v1.0"));
Pro hostované Blazor řešení založené na Blazor WebAssembly šabloně projektu je IWebAssemblyHostEnvironment.BaseAddress (new Uri(builder.HostEnvironment.BaseAddress)) přiřazeno k HttpClient.BaseAddress.
Předchozí registrace je navíc k existující zabezpečené výchozí HttpClient registraci.
Komponenta vytvoří HttpClient z IHttpClientFactory (Microsoft.Extensions.Http balíčku), aby vytvářela neověřené nebo neoprávněné požadavky:
@inject IHttpClientFactory ClientFactory
...
@code {
protected override async Task OnInitializedAsync()
{
var client = ClientFactory.CreateClient("WebAPI.NoAuthenticationClient");
var examples = await client.GetFromJsonAsync<ExampleType[]>(
"ExampleNoAuthentication");
...
}
}
Note
Kontroler v rozhraní API serveru v ExampleNoAuthenticationController předchozím příkladu není označen atributem[Authorize].
Rozhodnutí, jestli použít zabezpečeného klienta nebo nezabezpečeného klienta jako výchozí HttpClient instanci, je až na vývojáři. Jedním ze způsobů, jak toto rozhodnutí provést, je zvážit počet ověřených a neověřených koncových bodů, které kontaktují aplikace. Pokud je většina požadavků aplikace na zabezpečení koncových bodů rozhraní API, použijte ověřenou HttpClient instanci jako výchozí. V opačném případě zaregistrujte neověřenou HttpClient instanci jako výchozí.
Alternativním přístupem k použití IHttpClientFactory je vytvoření typového klienta pro neověřený přístup k anonymním koncovým bodům.
Vyžádání dalších přístupových tokenů
Přístupové tokeny lze získat ručně voláním IAccessTokenProvider.RequestAccessToken. V následujícím příkladu je pro výchozí HttpClient vyžadován další rozsah aplikace. Příklad knihovny MSAL (Microsoft Authentication Library) konfiguruje obor takto: MsalProviderOptions
V souboru Program:
builder.Services.AddMsalAuthentication(options =>
{
...
options.ProviderOptions.AdditionalScopesToConsent.Add("{CUSTOM SCOPE 1}");
options.ProviderOptions.AdditionalScopesToConsent.Add("{CUSTOM SCOPE 2}");
}
{CUSTOM SCOPE 1} a {CUSTOM SCOPE 2} zástupné symboly v předchozím příkladu jsou vlastní rozsahy.
Note
AdditionalScopesToConsent Není možné zřídit delegovaná uživatelská oprávnění pro Microsoft Graph prostřednictvím uživatelského rozhraní souhlasu s ID Microsoft Entra, když uživatel poprvé používá aplikaci zaregistrovanou v Microsoft Azure. Další informace najdete v tématu Použití rozhraní Graph API s ASP.NET Core Blazor WebAssembly.
Metoda IAccessTokenProvider.RequestAccessToken poskytuje možnost přetížení, které aplikaci umožňuje zřídit přístupový token s danou sadou rozsahů.
V komponentě Razor :
@using Microsoft.AspNetCore.Components.WebAssembly.Authentication
@inject IAccessTokenProvider TokenProvider
...
var tokenResult = await TokenProvider.RequestAccessToken(
new AccessTokenRequestOptions
{
Scopes = [ "{CUSTOM SCOPE 1}", "{CUSTOM SCOPE 2}" ]
});
if (tokenResult.TryGetToken(out var token))
{
...
}
@using Microsoft.AspNetCore.Components.WebAssembly.Authentication
@inject IAccessTokenProvider TokenProvider
...
var tokenResult = await TokenProvider.RequestAccessToken(
new AccessTokenRequestOptions
{
Scopes = new[] { "{CUSTOM SCOPE 1}", "{CUSTOM SCOPE 2}" }
});
if (tokenResult.TryGetToken(out var token))
{
...
}
{CUSTOM SCOPE 1} a {CUSTOM SCOPE 2} zástupné symboly v předchozím příkladu jsou vlastní rozsahy.
AccessTokenResult.TryGetToken výstupy:
-
truestokenk použití. -
falsepokud token není získán.
Sdílení prostředků mezi různými zdroji (CORS - Cross-Origin Resource Sharing)
Při odesílání přihlašovacích údajů (autorizační soubory cookie nebo hlavičky) u požadavků Authorization CORS musí být hlavička povolená zásadami CORS.
Následující zásady zahrnují konfiguraci pro:
- Požádat o původ (
http://localhost:5000,https://localhost:5001). - Libovolná metoda (sloveso).
-
Content-TypeaAuthorizationzáhlaví. Pokud chcete povolit vlastní záhlaví (napříkladx-custom-header), vypsat záhlaví při volání WithHeaders. - Přihlašovací údaje nastavené kódem JavaScriptu na straně klienta (
credentialsvlastnost nastavená nainclude).
app.UseCors(policy =>
policy.WithOrigins("http://localhost:5000", "https://localhost:5001")
.AllowAnyMethod()
.WithHeaders(HeaderNames.ContentType, HeaderNames.Authorization,
"x-custom-header")
.AllowCredentials());
Hostované Blazor řešení založené na Blazor WebAssembly šabloně projektu používá stejnou základní adresu pro klientské a serverové aplikace. Klientská HttpClient.BaseAddress aplikace je nastavená na identifikátor URI builder.HostEnvironment.BaseAddress. Konfigurace CORS se nevyžaduje ve výchozí konfiguraci hostovaného Blazor řešení. Další klientské aplikace, které nejsou hostované projektem serveru a nesdílejí základní adresu serverové aplikace, vyžadují konfiguraci CORS v projektu serveru.
Další informace najdete v tématu Povolení požadavků mezi zdroji (CORS) v ASP.NET Core a komponentě Tester požadavků HTTP ukázkové aplikace (Components/HTTPRequestTester.razor).
Zpracování chyb požadavků na token
Když jednostránková aplikace (SPA) ověřuje uživatele pomocí OpenID Connect (OIDC), stav ověřování se udržuje místně v rámci SPA a u poskytovatele identity (IP) ve formě relace, která je nastavena v důsledku zadání přihlašovacích údajů uživatele.
Tokeny, které IP adresa generuje pro uživatele, jsou obvykle platné po krátkou dobu přibližně jednu hodinu, takže klientská aplikace musí pravidelně načítat nové tokeny. Jinak by se uživatel odhlásil po vypršení platnosti udělených tokenů. Ve většině případů mohou klienti OIDC zřizovat nové tokeny, aniž by uživatel musel znovu projít autentizací, díky stavu ověřování nebo relaci, která se uchovává v rámci IP adresy.
V některých případech klient nemůže získat token bez zásahu uživatele, například když se uživatel z nějakého důvodu explicitně odhlásí z IP adresy. K tomuto scénáři dochází v případě, že uživatel navštíví https://login.microsoftonline.com a odhlásí se. V těchto scénářích aplikace okamžitě neví, že se uživatel odhlásil. Jakýkoli token, který klient uchovává, už nemusí být platný. Klient také nemůže zřídit nový token bez zásahu uživatele po vypršení platnosti aktuálního tokenu.
Tyto scénáře nejsou specifické pro ověřování založené na tokenech. Jsou součástí povahy spA. Jednostránková aplikace (SPA) využívající soubory cookie také nedokáže volat serverové API, pokud je ověřování cookie odebráno.
Když aplikace provádí volání rozhraní API pro chráněné prostředky, musíte mít na paměti následující skutečnosti:
- Pokud chcete zřídit nový přístupový token pro volání rozhraní API, může se stát, že se uživatel bude muset znovu ověřit.
- I když má klient token, který se zdá být platný, může volání serveru selhat, protože token byl odvolán uživatelem.
Když aplikace požádá o token, existují dva možné výsledky:
- Požadavek je úspěšný a aplikace má platný token.
- Požadavek selže a aplikace musí znovu ověřit uživatele, aby získal nový token.
Pokud požadavek na token selže, musíte se rozhodnout, jestli chcete před přesměrováním uložit libovolný aktuální stav. Existuje několik přístupů k ukládání stavu s rostoucí úrovní složitosti:
- Uložte aktuální stav stránky do session storage.
OnInitializedAsyncBěhem metody životního cyklu (OnInitializedAsync) před pokračováním zkontrolujte, jestli je možné obnovit stav. - Přidejte parametr řetězce dotazu a použijte ho jako způsob, jak signalizovat aplikaci, že potřebuje znovu hydratovat dříve uložený stav.
- Přidejte parametr řetězce dotazu s jedinečným identifikátorem pro ukládání dat do úložiště relací bez rizika kolizí s jinými položkami.
Uložení stavu aplikace před operací ověřování s úložištěm relací
Následující příklad ukazuje, jak:
- Zachovat stav před přesměrováním na přihlašovací stránku.
- Obnovení předchozího stavu po ověření pomocí parametru řetězce dotazu
...
@using System.Text.Json
@using Microsoft.AspNetCore.Components.WebAssembly.Authentication
@inject IAccessTokenProvider TokenProvider
@inject IJSRuntime JS
@inject NavigationManager Navigation
<EditForm Model="User" OnSubmit="OnSaveAsync">
<label>
First Name:
<InputText @bind-Value="User!.Name" />
</label>
<label>
Last Name:
<InputText @bind-Value="User!.LastName" />
</label>
<button type="submit">Save User</button>
</EditForm>
@code {
public Profile User { get; set; } = new Profile();
protected override async Task OnInitializedAsync()
{
var currentQuery = new Uri(Navigation.Uri).Query;
if (currentQuery.Contains("state=resumeSavingProfile"))
{
var user = await JS.InvokeAsync<string>("sessionStorage.getItem",
"resumeSavingProfile");
if (!string.IsNullOrEmpty(user))
{
User = JsonSerializer.Deserialize<Profile>(user);
}
}
}
public async Task OnSaveAsync()
{
var http = new HttpClient();
http.BaseAddress = new Uri(Navigation.BaseUri);
var resumeUri = Navigation.Uri + $"?state=resumeSavingProfile";
var tokenResult = await TokenProvider.RequestAccessToken(
new AccessTokenRequestOptions
{
ReturnUrl = resumeUri
});
if (tokenResult.TryGetToken(out var token))
{
http.DefaultRequestHeaders.Add("Authorization",
$"Bearer {token.Value}");
await http.PostAsJsonAsync("Save", User);
}
else
{
await JS.InvokeVoidAsync("sessionStorage.setItem",
"resumeSavingProfile", JsonSerializer.Serialize(User));
Navigation.NavigateTo(tokenResult.InteractiveRequestUrl);
}
}
public class Profile
{
public string? FirstName { get; set; }
public string? LastName { get; set; }
}
}
Uložení stavu aplikace před operací ověřování s úložištěm relací a kontejnerem stavu
Během operace ověřování existují případy, kdy chcete před přesměrováním prohlížeče na IP adresu uložit stav aplikace. To může být případ, kdy používáte kontejner stavu a chcete obnovit stav po úspěšném ověření. Vlastní objekt stavu ověřování můžete použít k zachování stavu specifického pro aplikaci nebo odkazu na něj a obnovení tohoto stavu po úspěšném dokončení operace ověřování. Následující příklad ukazuje přístup.
V aplikaci se vytvoří třída kontejneru stavu s vlastnostmi, které budou obsahovat hodnoty stavu aplikace. V následujícím příkladu se kontejner používá k zachování hodnoty čítače komponenty výchozí Blazor šablonyCounter projektu (Counter.razor). Metody serializace a deserializace kontejneru jsou založeny na System.Text.Json.
using System.Text.Json;
public class StateContainer
{
public int CounterValue { get; set; }
public string GetStateForLocalStorage() => JsonSerializer.Serialize(this);
public void SetStateFromLocalStorage(string locallyStoredState)
{
var deserializedState =
JsonSerializer.Deserialize<StateContainer>(locallyStoredState);
CounterValue = deserializedState.CounterValue;
}
}
Komponenta Counter používá kontejner stavu k udržování currentCount hodnoty mimo komponentu:
@page "/counter"
@inject StateContainer State
<h1>Counter</h1>
<p>Current count: @currentCount</p>
<button class="btn btn-primary" @onclick="IncrementCount">Click me</button>
@code {
private int currentCount = 0;
protected override void OnInitialized()
{
if (State.CounterValue > 0)
{
currentCount = State.CounterValue;
}
}
private void IncrementCount()
{
currentCount++;
State.CounterValue = currentCount;
}
}
Vytvořit ApplicationAuthenticationState z RemoteAuthenticationState.
Id Zadejte vlastnost, která slouží jako identifikátor místně uloženého stavu.
ApplicationAuthenticationState.cs:
using Microsoft.AspNetCore.Components.WebAssembly.Authentication;
public class ApplicationAuthenticationState : RemoteAuthenticationState
{
public string? Id { get; set; }
}
Komponenta Authentication (Authentication.razor) uloží a obnoví stav aplikace pomocí místního úložiště relací s metodami StateContainer serializace a deserializace a GetStateForLocalStorageSetStateFromLocalStorage:
@page "/authentication/{action}"
@using Microsoft.AspNetCore.Components.WebAssembly.Authentication
@inject IJSRuntime JS
@inject StateContainer State
<RemoteAuthenticatorViewCore Action="Action"
TAuthenticationState="ApplicationAuthenticationState"
AuthenticationState="AuthenticationState"
OnLogInSucceeded="RestoreState"
OnLogOutSucceeded="RestoreState" />
@code {
[Parameter]
public string? Action { get; set; }
public ApplicationAuthenticationState AuthenticationState { get; set; } =
new ApplicationAuthenticationState();
protected override async Task OnInitializedAsync()
{
if (RemoteAuthenticationActions.IsAction(RemoteAuthenticationActions.LogIn,
Action) ||
RemoteAuthenticationActions.IsAction(RemoteAuthenticationActions.LogOut,
Action))
{
AuthenticationState.Id = Guid.NewGuid().ToString();
await JS.InvokeVoidAsync("sessionStorage.setItem",
AuthenticationState.Id, State.GetStateForLocalStorage());
}
}
private async Task RestoreState(ApplicationAuthenticationState state)
{
if (state.Id != null)
{
var locallyStoredState = await JS.InvokeAsync<string>(
"sessionStorage.getItem", state.Id);
if (locallyStoredState != null)
{
State.SetStateFromLocalStorage(locallyStoredState);
await JS.InvokeVoidAsync("sessionStorage.removeItem", state.Id);
}
}
}
}
V tomto příkladu se k ověřování používá Microsoft Entra (ME-ID). V souboru Program:
-
ApplicationAuthenticationStateje nakonfigurován jako typ knihovny Microsoft Authentication Library (MSAL)RemoteAuthenticationState. - Kontejner stavu je zaregistrovaný v kontejneru služeb.
builder.Services.AddMsalAuthentication<ApplicationAuthenticationState>(options =>
{
builder.Configuration.Bind("AzureAd", options.ProviderOptions.Authentication);
});
builder.Services.AddSingleton<StateContainer>();
Přizpůsobení tras aplikací
Knihovna Microsoft.AspNetCore.Components.WebAssembly.Authentication používá trasy uvedené v následující tabulce pro reprezentaci různých stavů ověřování.
| Route | Purpose |
|---|---|
authentication/login |
Aktivuje operaci přihlášení. |
authentication/login-callback |
Zpracovává výsledek jakékoli operace přihlášení. |
authentication/login-failed |
Zobrazí chybové zprávy, když operace přihlášení z nějakého důvodu selže. |
authentication/logout |
Aktivuje operaci odhlášení. |
authentication/logout-callback |
Zpracovává výsledek operace odhlášení. |
authentication/logout-failed |
Zobrazí chybové zprávy, když operace odhlášení z nějakého důvodu selže. |
authentication/logged-out |
Označuje, že se uživatel úspěšně odhlásí. |
authentication/profile |
Aktivuje operaci pro úpravu profilu uživatele. |
authentication/register |
Aktivuje operaci pro registraci nového uživatele. |
Trasy uvedené v předchozí tabulce jsou konfigurovatelné prostřednictvím RemoteAuthenticationOptions<TRemoteAuthenticationProviderOptions>.AuthenticationPaths. Při nastavování možností poskytnutí vlastních tras ověřte, že aplikace má trasu, která zpracovává jednotlivé cesty.
V následujícím příkladu jsou všechny cesty opatřeny předponou /security.
Authentication součást (Authentication.razor):
@page "/security/{action}"
@using Microsoft.AspNetCore.Components.WebAssembly.Authentication
<RemoteAuthenticatorView Action="@Action" />
@code{
[Parameter]
public string? Action { get; set; }
}
@page "/security/{action}"
@using Microsoft.AspNetCore.Components.WebAssembly.Authentication
<RemoteAuthenticatorView Action="@Action" />
@code{
[Parameter]
public string Action { get; set; }
}
V souboru Program:
builder.Services.AddApiAuthorization(options => {
options.AuthenticationPaths.LogInPath = "security/login";
options.AuthenticationPaths.LogInCallbackPath = "security/login-callback";
options.AuthenticationPaths.LogInFailedPath = "security/login-failed";
options.AuthenticationPaths.LogOutPath = "security/logout";
options.AuthenticationPaths.LogOutCallbackPath = "security/logout-callback";
options.AuthenticationPaths.LogOutFailedPath = "security/logout-failed";
options.AuthenticationPaths.LogOutSucceededPath = "security/logged-out";
options.AuthenticationPaths.ProfilePath = "security/profile";
options.AuthenticationPaths.RegisterPath = "security/register";
});
Pokud jsou požadovány zcela jiné trasy, nastavte tyto trasy, jak je popsáno výše, a vykreslujte RemoteAuthenticatorView s explicitním parametrem akce:
@page "/register"
<RemoteAuthenticatorView Action="RemoteAuthenticationActions.Register" />
Pokud se tak rozhodnete, můžete uživatelské rozhraní rozdělit na různé stránky.
Přizpůsobení uživatelského rozhraní ověřování
RemoteAuthenticatorView obsahuje výchozí sadu fragmentů uživatelského rozhraní pro každý stav ověřování. Každý stav lze přizpůsobit předáním vlastního RenderFragment. Chcete-li přizpůsobit zobrazený text během počátečního procesu přihlášení, můžete změnit RemoteAuthenticatorView následujícím způsobem.
Authentication součást (Authentication.razor):
@page "/security/{action}"
@using Microsoft.AspNetCore.Components.WebAssembly.Authentication
<RemoteAuthenticatorView Action="@Action">
<LoggingIn>
You are about to be redirected to https://login.microsoftonline.com.
</LoggingIn>
</RemoteAuthenticatorView>
@code{
[Parameter]
public string? Action { get; set; }
}
@page "/security/{action}"
@using Microsoft.AspNetCore.Components.WebAssembly.Authentication
<RemoteAuthenticatorView Action="@Action">
<LoggingIn>
You are about to be redirected to https://login.microsoftonline.com.
</LoggingIn>
</RemoteAuthenticatorView>
@code{
[Parameter]
public string Action { get; set; }
}
Obsahuje RemoteAuthenticatorView jeden fragment, který lze použít pro každou trasu ověřování uvedenou v následující tabulce.
| Route | Fragment |
|---|---|
authentication/login |
<LoggingIn> |
authentication/login-callback |
<CompletingLoggingIn> |
authentication/login-failed |
<LogInFailed> |
authentication/logout |
<LogOut> |
authentication/logout-callback |
<CompletingLogOut> |
authentication/logout-failed |
<LogOutFailed> |
authentication/logged-out |
<LogOutSucceeded> |
authentication/profile |
<UserProfile> |
authentication/register |
<Registering> |
Přizpůsobení uživatele
Uživatele vázané na aplikaci je možné přizpůsobit.
Přizpůsobte uživatele pomocí deklarace datové části
V následujícím příkladu obdrží ověření uživatelé amr aplikace deklaraci identity pro každou metodu ověřování uživatele. Nárok amr určuje, jakým způsobem byl subjekt tokenu ověřen pomocí nároků v Microsoft identity platform v1.0. Příklad používá vlastní třídu uživatelských účtů založenou na RemoteUserAccount.
Vytvořte třídu, která rozšiřuje RemoteUserAccount třídu. Následující příklad nastaví AuthenticationMethod vlastnost na uživatelovo pole hodnot vlastností amr JSON.
AuthenticationMethod je automaticky vyplněna rozhraním při ověření uživatele.
using System.Text.Json.Serialization;
using Microsoft.AspNetCore.Components.WebAssembly.Authentication;
public class CustomUserAccount : RemoteUserAccount
{
[JsonPropertyName("amr")]
public string[]? AuthenticationMethod { get; set; }
}
Vytvořte továrnu, která rozšiřuje AccountClaimsPrincipalFactory<TAccount> a vytváří deklarace identity z metod ověřování uživatele uložených v CustomUserAccount.AuthenticationMethod.
using System.Security.Claims;
using Microsoft.AspNetCore.Components;
using Microsoft.AspNetCore.Components.WebAssembly.Authentication;
using Microsoft.AspNetCore.Components.WebAssembly.Authentication.Internal;
public class CustomAccountFactory(NavigationManager navigation,
IAccessTokenProviderAccessor accessor)
: AccountClaimsPrincipalFactory<CustomUserAccount>(accessor)
{
public override async ValueTask<ClaimsPrincipal> CreateUserAsync(
CustomUserAccount account, RemoteAuthenticationUserOptions options)
{
var initialUser = await base.CreateUserAsync(account, options);
if (initialUser.Identity != null && initialUser.Identity.IsAuthenticated)
{
var userIdentity = (ClaimsIdentity)initialUser.Identity;
if (account.AuthenticationMethod is not null)
{
foreach (var value in account.AuthenticationMethod)
{
userIdentity.AddClaim(new Claim("amr", value));
}
}
}
return initialUser;
}
}
Zaregistrujte CustomAccountFactory pro používaného zprostředkovatele ověřování. Některé z následujících registrací jsou platné:
-
using Microsoft.AspNetCore.Components.WebAssembly.Authentication; ... builder.Services.AddOidcAuthentication<RemoteAuthenticationState, CustomUserAccount>(options => { ... }) .AddAccountClaimsPrincipalFactory<RemoteAuthenticationState, CustomUserAccount, CustomAccountFactory>(); -
using Microsoft.AspNetCore.Components.WebAssembly.Authentication; ... builder.Services.AddMsalAuthentication<RemoteAuthenticationState, CustomUserAccount>(options => { ... }) .AddAccountClaimsPrincipalFactory<RemoteAuthenticationState, CustomUserAccount, CustomAccountFactory>(); -
using Microsoft.AspNetCore.Components.WebAssembly.Authentication; ... builder.Services.AddApiAuthorization<RemoteAuthenticationState, CustomUserAccount>(options => { ... }) .AddAccountClaimsPrincipalFactory<RemoteAuthenticationState, CustomUserAccount, CustomAccountFactory>();
Skupiny zabezpečení ME-ID a role s vlastní třídou uživatelského účtu
Další příklad, který funguje se skupinami zabezpečení ME-ID a rolemi správce ME-ID a vlastní třídou uživatelských účtů, najdete v tématu ASP.NET Core Blazor WebAssembly se skupinami a rolemi ID Microsoft Entra.
Předběžné vykreslování s ověřováním
Předběžné nastavení obsahu, který vyžaduje ověřování a autorizaci, se v současné době nepodporuje. Po provedení pokynů v jednom z Blazor WebAssembly témat aplikace zabezpečení pomocí následujících pokynů vytvořte aplikaci, která:
- Předem vykresluje cesty, pro které není vyžadováno povolení.
- Nepředvykresluje trasy, pro které je vyžadována autorizace.
U souboru projektu Client souboru Program shrňte běžné registrace služeb do samostatné metody (například vytvořte metodu ConfigureCommonServices v projektu Client). Mezi běžné služby patří ty, které vývojář zaregistruje pro použití v projektech klienta i serveru.
public static void ConfigureCommonServices(IServiceCollection services)
{
services.Add...;
}
V souboru Program:
var builder = WebAssemblyHostBuilder.CreateDefault(args);
...
builder.Services.AddScoped( ... );
ConfigureCommonServices(builder.Services);
await builder.Build().RunAsync();
Server V souboru projektu Program zaregistrujte následující další služby a volejteConfigureCommonServices:
using Microsoft.AspNetCore.Components.Authorization;
using Microsoft.AspNetCore.Components.Server;
using Microsoft.AspNetCore.Components.WebAssembly.Authentication;
...
builder.Services.AddRazorPages();
builder.Services.TryAddScoped<AuthenticationStateProvider,
ServerAuthenticationStateProvider>();
Client.Program.ConfigureCommonServices(services);
Server V metodě projektu Startup.ConfigureServices zaregistrujte následující další služby a volejteConfigureCommonServices:
using Microsoft.AspNetCore.Components.Authorization;
using Microsoft.AspNetCore.Components.Server;
using Microsoft.AspNetCore.Components.WebAssembly.Authentication;
public void ConfigureServices(IServiceCollection services)
{
...
services.AddRazorPages();
services.AddScoped<AuthenticationStateProvider,
ServerAuthenticationStateProvider>();
services.AddScoped<SignOutSessionStateManager>();
Client.Program.ConfigureCommonServices(services);
}
Další informace o zprostředkovateli ověřování serveru frameworku (Blazor, ServerAuthenticationStateProvider) najdete v tématu Autentizace a autorizace jádra ASP.NET Blazor.
V souboru projektu ServerPages/_Host.cshtml, nahraďte pomocníka značek Component(<component ... />) následujícím:
<div id="app">
@if (HttpContext.Request.Path.StartsWithSegments("/authentication"))
{
<component type="typeof({CLIENT APP ASSEMBLY NAME}.App)"
render-mode="WebAssembly" />
}
else
{
<component type="typeof({CLIENT APP ASSEMBLY NAME}.App)"
render-mode="WebAssemblyPrerendered" />
}
</div>
V předchozím příkladu:
- Zástupný
{CLIENT APP ASSEMBLY NAME}symbol je název sestavení klientské aplikace (napříkladBlazorSample.Client). - Podmíněná kontrola segmentu cesty
/authentication:- Předběžné vykreslování (
render-mode="WebAssembly") se vynechává pro cesty ověřování. - Prerenders (
render-mode="WebAssemblyPrerendered") pro trasy bez ověřování.
- Předběžné vykreslování (
Možnosti hostovaných aplikací a poskytovatelů přihlášení třetích stran
Při ověřování a autorizaci hostované Blazor WebAssembly aplikace u poskytovatele třetí strany je k dispozici několik možností pro ověření uživatele. Který z nich zvolíte, závisí na vašem scénáři.
Další informace najdete v tématu věnovaném zachování dalších deklarací identity a tokenů od externích zprostředkovatelů v ASP.NET Core.
Ověřte uživatele, aby mohli volat pouze chráněná API třetích stran.
Ověřte uživatele pomocí toku OAuth na straně klienta vůči poskytovateli rozhraní API třetí strany:
builder.services.AddOidcAuthentication(options => { ... });
V tomto scénáři:
- Server, který je hostitelem aplikace, nehraje roli.
- Rozhraní API na serveru nemohou být chráněna.
- Aplikace může volat pouze chráněná rozhraní API třetích stran.
Ověřování uživatelů pomocí poskytovatele třetí strany a volání chráněných rozhraní API na hostitelském serveru a třetí straně
Konfigurujte Identity s poskytovatelem přihlášení třetí strany. Získejte tokeny potřebné pro přístup k rozhraní API třetích stran a uložte je.
Když se uživatel přihlásí, Identity shromažďuje v rámci procesu ověřování přístup a obnovovací tokeny. V tomto okamžiku je k dispozici několik způsobů volání API třetích stran.
Použití přístupového tokenu serveru k načtení přístupového tokenu třetí strany
Přístupový token vygenerovaný na serveru použijte k načtení přístupového tokenu třetí strany z koncového bodu rozhraní API serveru. Odtud použijte přístupový token třetí strany k volání prostředků rozhraní API třetích stran přímo z Identity klienta.
Tento přístup nedoporučujeme. Tento přístup vyžaduje zacházení s přístupovým tokenem třetí strany, jako by byl vygenerován pro veřejného klienta. Pokud jde o OAuth, veřejná aplikace nemá tajný klíč klienta, protože nemůže být důvěryhodná pro bezpečné ukládání tajných kódů a přístupový token se vytvoří pro důvěrného klienta. Důvěrný klient je klient, který má tajný klíč klienta a předpokládá se, že může bezpečně ukládat tajné kódy.
- Přístupový token třetí strany může být udělen další obory pro provádění citlivých operací na základě skutečnosti, že třetí strana token vygenerovala pro důvěryhodnějšího klienta.
- Podobně by obnovovací tokeny neměly být vystaveny klientovi, kterému není důvěryhodný, protože tím dáváte klientovi neomezený přístup, pokud nejsou zavedena jiná omezení.
Volání rozhraní API z klienta na serverové rozhraní API za účelem volání rozhraní API třetích stran
Zavolejte API z klienta na API serveru. Ze serveru načtěte přístupový token pro prostředek rozhraní API třetí strany a zadejte jakékoli volání, které je potřeba.
Tento přístup doporučujeme. I když tento přístup vyžaduje další síťový skok přes server, aby volal rozhraní API třetí strany, nakonec je výsledkem bezpečnější prostředí:
- Server může ukládat obnovovací tokeny a zajistit, aby aplikace nepřišla o přístup k prostředkům třetích stran.
- Aplikace nemůže vytékat přístupové tokeny ze serveru, které můžou obsahovat citlivější oprávnění.
Použití koncových bodů OpenID Connect (OIDC) v2.0
Knihovna ověřování a Blazor šablony projektů používají koncové body OpenID Connect (OIDC) v1.0. Pokud chcete použít koncový bod verze 2.0, nakonfigurujte možnost Nosný JwtBearerOptions.Authority objekt JWT. V následujícím příkladu je ME-ID nakonfigurováno pro v2.0 připojením v2.0 segmentu k Authority vlastnosti:
using Microsoft.AspNetCore.Authentication.JwtBearer;
...
builder.Services.Configure<JwtBearerOptions>(
JwtBearerDefaults.AuthenticationScheme,
options =>
{
options.Authority += "/v2.0";
});
Případně můžete nastavení provést v souboru nastavení aplikace (appsettings.json):
{
"Local": {
"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 JwtBearerOptions, nebo v souboru nastavení aplikace (appsettings.json) s klíčem Authority.
Seznam nároků v ID tokenu 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.
Konfigurace a použití gRPC v součástech
Konfigurace Blazor WebAssembly aplikace tak, aby používala architekturu ASP.NET Core gRPC:
- Povolte na serveru gRPC-Web. Další informace najdete v tématu gRPC-Web v aplikacích ASP.NET Core gRPC.
- Registrujte služby gRPC pro handler zpráv aplikace. Následující příklad nakonfiguruje obslužnou rutinu autorizační zprávy aplikace tak, aby používala službu z
GreeterClient( soubor).
Note
Předběžné vykreslování je ve výchozím nastavení povolené ve Blazor Web Apps, takže musíte nejprve zohlednit vykreslování komponent ze serveru a potom z klienta. Jakýkoli předem uspořádaný stav by měl do klienta proudit, aby ho bylo možné znovu použít. Další informace najdete v tématu ASP.NET Blazor trvalost stavu předsekutného jádra.
Note
Předběžné vykreslování je ve výchozím nastavení povolené v hostovaných Blazor WebAssembly aplikacích, takže musíte nejprve počítat s vykreslováním komponent ze serveru a potom z klienta. Jakýkoli předem uspořádaný stav by měl do klienta proudit, aby ho bylo možné znovu použít. Další informace najdete v tématu Integrace komponent ASP.NET Core Razor s MVC nebo Razor Stránkami v hostovaných Blazor WebAssembly řešeních.
using System.Net.Http;
using Microsoft.AspNetCore.Components.WebAssembly.Authentication;
using Grpc.Net.Client;
using Grpc.Net.Client.Web;
...
builder.Services.AddScoped(sp =>
{
var baseAddressMessageHandler =
sp.GetRequiredService<BaseAddressAuthorizationMessageHandler>();
baseAddressMessageHandler.InnerHandler = new HttpClientHandler();
var grpcWebHandler =
new GrpcWebHandler(GrpcWebMode.GrpcWeb, baseAddressMessageHandler);
var channel = GrpcChannel.ForAddress(builder.HostEnvironment.BaseAddress,
new GrpcChannelOptions { HttpHandler = grpcWebHandler });
return new Greeter.GreeterClient(channel);
});
Komponenta v klientské aplikaci může provádět volání gRPC pomocí klienta gRPC (Grpc.razor):
@page "/grpc"
@using Microsoft.AspNetCore.Authorization
@attribute [Authorize]
@inject Greeter.GreeterClient GreeterClient
<h1>Invoke gRPC service</h1>
<p>
<input @bind="name" placeholder="Type your name" />
<button @onclick="GetGreeting" class="btn btn-primary">Call gRPC service</button>
</p>
Server response: <strong>@serverResponse</strong>
@code {
private string name = "Bert";
private string? serverResponse;
private async Task GetGreeting()
{
try
{
var request = new HelloRequest { Name = name };
var reply = await GreeterClient.SayHelloAsync(request);
serverResponse = reply.Message;
}
catch (Grpc.Core.RpcException ex)
when (ex.Status.DebugException is
AccessTokenNotAvailableException tokenEx)
{
tokenEx.Redirect();
}
}
}
Pokud chcete použít Status.DebugException vlastnost, použijte Grpc.Net.Client verzi 2.30.0 nebo novější.
Další informace najdete v tématu gRPC-Web v aplikacích ASP.NET Core gRPC.
AuthenticationService Nahrazení implementace
Následující pododdíly vysvětlují, jak nahradit:
- Jakákoli implementace JavaScriptu
AuthenticationService - Microsoft Authentication Library pro JavaScript (
MSAL.js).
Nahrazení jakékoli implementace JavaScriptu AuthenticationService
Vytvořte javascriptovou knihovnu pro zpracování vlastních podrobností ověřování.
Warning
Pokyny v této části jsou podrobností implementace výchozího RemoteAuthenticationService<TRemoteAuthenticationState,TAccount,TProviderOptions>. Kód TypeScriptu v této části se vztahuje konkrétně na ASP.NET Core v .NET 7 a v nadcházejících verzích ASP.NET Core se může změnit bez předchozího upozornění.
// .NET makes calls to an AuthenticationService object in the Window.
declare global {
interface Window { AuthenticationService: AuthenticationService }
}
export interface AuthenticationService {
// Init is called to initialize the AuthenticationService.
public static init(settings: UserManagerSettings & AuthorizeServiceSettings, logger: any) : Promise<void>;
// Gets the currently authenticated user.
public static getUser() : Promise<{[key: string] : string }>;
// Tries to get an access token silently.
public static getAccessToken(options: AccessTokenRequestOptions) : Promise<AccessTokenResult>;
// Tries to sign in the user or get an access token interactively.
public static signIn(context: AuthenticationContext) : Promise<AuthenticationResult>;
// Handles the sign-in process when a redirect is used.
public static async completeSignIn(url: string) : Promise<AuthenticationResult>;
// Signs the user out.
public static signOut(context: AuthenticationContext) : Promise<AuthenticationResult>;
// Handles the signout callback when a redirect is used.
public static async completeSignOut(url: string) : Promise<AuthenticationResult>;
}
// The rest of these interfaces match their C# definitions.
export interface AccessTokenRequestOptions {
scopes: string[];
returnUrl: string;
}
export interface AccessTokenResult {
status: AccessTokenResultStatus;
token?: AccessToken;
}
export interface AccessToken {
value: string;
expires: Date;
grantedScopes: string[];
}
export enum AccessTokenResultStatus {
Success = 'Success',
RequiresRedirect = 'RequiresRedirect'
}
export enum AuthenticationResultStatus {
Redirect = 'Redirect',
Success = 'Success',
Failure = 'Failure',
OperationCompleted = 'OperationCompleted'
};
export interface AuthenticationResult {
status: AuthenticationResultStatus;
state?: unknown;
message?: string;
}
export interface AuthenticationContext {
state?: unknown;
interactiveRequest: InteractiveAuthenticationRequest;
}
export interface InteractiveAuthenticationRequest {
scopes?: string[];
additionalRequestParameters?: { [key: string]: any };
};
Knihovnu můžete importovat odebráním původní <script> značky a přidáním <script> značky, která načte vlastní knihovnu. Následující příklad ukazuje nahrazení výchozí <script> značky za značku, která načte knihovnu CustomAuthenticationService.js pojmenovanou wwwroot/js ze složky.
wwwroot/index.html Před Blazor skriptem (_framework/blazor.webassembly.js) uvnitř koncové </body> značky:
- <script src="_content/Microsoft.Authentication.WebAssembly.Msal/AuthenticationService.js"></script>
+ <script src="js/CustomAuthenticationService.js"></script>
Další informace najdete AuthenticationService.ts v dotnet/aspnetcore úložišti GitHub.
Note
Odkazy na dokumentaci k referenčnímu zdroji .NET obvykle načítají výchozí větev úložiště, která představuje aktuální vývoj pro příští verzi .NET. Pokud chcete vybrat značku pro konkrétní verzi, použijte rozevírací seznam pro přepínání větví nebo značek. Další informace najdete v tématu Jak vybrat značku verze zdrojového kódu ASP.NET Core (dotnet/AspNetCore.Docs #26205).
Nahrazení knihovny Microsoft Authentication Library pro JavaScript (MSAL.js)
Pokud aplikace vyžaduje vlastní verzi knihovny Microsoft Authentication pro JavaScript (MSAL.js), proveďte následující kroky:
- Ověřte, že systém obsahuje nejnovější sadu .NET SDK pro vývojáře, nebo získejte a nainstalujte nejnovější sadu SDK pro vývojáře ze sady .NET SDK: Instalační programy a binární soubory. Pro tento scénář není nutná konfigurace interních informačních kanálů NuGet.
- Nastavte úložiště GitHub pro vývoj podle dokumentu
dotnet/aspnetcore. Vytvořte fork a naklonujte nebo stáhněte archiv ZIP úložištědotnet/aspnetcoreGitHub. - Otevřete
src/Components/WebAssembly/Authentication.Msal/src/Interop/package.jsonsoubor a nastavte požadovanou verzi@azure/msal-browser. Seznam vydaných verzí najdete na@azure/msal-browserwebu npm a vyberte kartu Verze . -
Authentication.MsalSestavte projekt vesrc/Components/WebAssembly/Authentication.Msal/srcsložce pomocíyarn buildpříkazu v příkazovém prostředí. - Pokud aplikace používá komprimované prostředky (Brotli/Gzip), komprimujte
Interop/dist/Release/AuthenticationService.jssoubor. - Zkopírujte soubor
AuthenticationService.jsa jeho komprimované verze (.br/.gz) (pokud se vytvoří) ze složkyInterop/dist/Releasedo složkypublish/wwwroot/_content/Microsoft.Authentication.WebAssembly.Msalv publikovaných prostředcích aplikace.
Předání možností vlastního zprostředkovatele
Definujte třídu pro předávání dat do podkladové javascriptové knihovny.
Important
Struktura třídy musí odpovídat tomu, co knihovna očekává, když je JSON serializován s System.Text.Json.
Následující příklad ukazuje ProviderOptions třídu s JsonPropertyName atributy, které odpovídají očekávání hypotetické knihovny vlastních poskytovatelů:
public class ProviderOptions
{
public string? Authority { get; set; }
public string? MetadataUrl { get; set; }
[JsonPropertyName("client_id")]
public string? ClientId { get; set; }
public IList<string> DefaultScopes { get; set; } = [ "openid", "profile" ];
[JsonPropertyName("redirect_uri")]
public string? RedirectUri { get; set; }
[JsonPropertyName("post_logout_redirect_uri")]
public string? PostLogoutRedirectUri { get; set; }
[JsonPropertyName("response_type")]
public string? ResponseType { get; set; }
[JsonPropertyName("response_mode")]
public string? ResponseMode { get; set; }
}
Zaregistrujte možnosti poskytovatele v systému DI a nakonfigurujte příslušné hodnoty:
builder.Services.AddRemoteAuthentication<RemoteAuthenticationState, RemoteUserAccount,
ProviderOptions>(options => {
options.ProviderOptions.Authority = "...";
options.ProviderOptions.MetadataUrl = "...";
options.ProviderOptions.ClientId = "...";
options.ProviderOptions.DefaultScopes = [ "openid", "profile", "myApi" ];
options.ProviderOptions.RedirectUri = "https://localhost:5001/authentication/login-callback";
options.ProviderOptions.PostLogoutRedirectUri = "https://localhost:5001/authentication/logout-callback";
options.ProviderOptions.ResponseType = "...";
options.ProviderOptions.ResponseMode = "...";
});
Předchozí příklad nastaví identifikátory URI přesměrování s běžnými textovými literály. K dispozici jsou následující alternativy:
TryCreate použití IWebAssemblyHostEnvironment.BaseAddress:
Uri.TryCreate( $"{builder.HostEnvironment.BaseAddress}authentication/login-callback", UriKind.Absolute, out var redirectUri); options.RedirectUri = redirectUri;Konfigurace sestavení hostitele:
options.RedirectUri = builder.Configuration["RedirectUri"];wwwroot/appsettings.json:{ "RedirectUri": "https://localhost:5001/authentication/login-callback" }