ASP.NET Core Blazor WebAssembly ek güvenlik senaryoları
Uyarı
ASP.NET Core'un bu sürümü artık desteklenmiyor. Daha fazla bilgi için bkz . .NET ve .NET Core Destek İlkesi. Geçerli sürüm için bu makalenin .NET 8 sürümüne bakın.
Bu makalede, uygulamalar için Blazor WebAssembly ek güvenlik senaryoları açıklanmaktadır.
Giden isteklere belirteç ekleme
AuthorizationMessageHandlerDelegatingHandler erişim belirteçlerini işlemek için kullanılır. Belirteçler, çerçeve tarafından kaydedilen hizmet kullanılarak IAccessTokenProvider alınır. Belirteç alınamazsa, bir AccessTokenNotAvailableException oluşturulur. AccessTokenNotAvailableException, erişim belirtecinin yenilenmesine AccessTokenResult.InteractiveRequestUrl izin vermek için verilen AccessTokenResult.InteractionOptions öğesini kullanmaya giden bir Redirect yönteme sahiptir.
Kolaylık olması için, çerçeve uygulamanın temel adresiyle önceden yapılandırılmış olan bir yetkili URL sağlar BaseAddressAuthorizationMessageHandler . Erişim belirteçleri yalnızca istek URI'sinin uygulamanın temel URI'sinde olması halinde eklenir. Giden istek URI'leri uygulamanın temel URI'sinde olmadığında, özel bir sınıf kullanın (önerilen) veya yapılandırınAuthorizationMessageHandler
.AuthorizationMessageHandler
Not
Sunucu API erişimi için istemci uygulama yapılandırmasına ek olarak, istemci ve sunucu aynı temel adreste olmadığında sunucu API'sinin çıkış noktaları arası isteklere (CORS) de izin vermesi gerekir. Sunucu tarafı CORS yapılandırması hakkında daha fazla bilgi için bu makalenin devamındaki Çıkış Noktaları Arası Kaynak Paylaşımı (CORS) bölümüne bakın.
Aşağıdaki örnekte:
- AddHttpClient hizmet koleksiyonuna ve ilgili hizmetleri ekler IHttpClientFactory ve adlandırılmış HttpClient bir ()
WebAPI
yapılandırır. HttpClient.BaseAddress , istek gönderirken kaynak URI'sinin temel adresidir. IHttpClientFactory NuGet paketi tarafındanMicrosoft.Extensions.Http
sağlanır. - BaseAddressAuthorizationMessageHandlerDelegatingHandler erişim belirteçlerini işlemek için kullanılır. Erişim belirteçleri yalnızca istek URI'sinin uygulamanın temel URI'sinde olması halinde eklenir.
- IHttpClientFactory.CreateClientadlı HttpClient ()
WebAPI
adlı öğeye karşılık gelen yapılandırmayı kullanarak giden istekler için bir HttpClient örnek oluşturur ve yapılandırılır.
Aşağıdaki örnekte, HttpClientFactoryServiceCollectionExtensions.AddHttpClient içindeki Microsoft.Extensions.Httpbir uzantıdır. Paketi, henüz başvurmayan bir uygulamaya ekleyin.
Not
.NET uygulamalarına paket ekleme hakkında yönergeler için, Paket tüketimi iş akışında (NuGet belgeleri) paketleri yüklemek ve yönetmek altındaki makalelere bakın. NuGet.org'da doğru paket sürümlerini onaylayın.
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"));
Proje şablonunu temel alan barındırılan Blazorbir çözüm için Blazor WebAssembly istek URI'leri uygulamanın temel URI'sinde yer alır. Bu nedenle, IWebAssemblyHostEnvironment.BaseAddress (new Uri(builder.HostEnvironment.BaseAddress)
) proje şablonundan oluşturulan bir uygulamada öğesine atanır HttpClient.BaseAddress .
Yapılandırılan HttpClient , deseni kullanarak try-catch
yetkili isteklerde bulunmak için kullanılır:
@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();
}
}
Özel kimlik doğrulama isteği senaryoları
Aşağıdaki senaryolarda, kimlik doğrulama isteklerini özelleştirme ve kimlik doğrulama seçeneklerinden oturum açma yolunun nasıl edinileceği gösterilmektedir.
Oturum açma işlemini özelleştirme
Yeni bir örneğinde bir veya daha fazla kez aşağıdaki yöntemlerle bir oturum açma isteğine InteractiveRequestOptionsyönelik ek parametreleri yönetin:
Aşağıdaki LoginDisplay
bileşen örneğinde, oturum açma isteğine ek parametreler eklenir:
prompt
olarak ayarlanırlogin
: Kullanıcıyı bu istekte kimlik bilgilerini girmeye zorlar ve çoklu oturum açmayı olumsuzlar.loginHint
olarak ayarlanırpeter@contoso.com
: Kullanıcının oturum açma sayfasınınpeter@contoso.com
kullanıcı adı/e-posta adresi alanını olarak önceden doldurur. Uygulamalar bu parametreyi genellikle yeniden kimlik doğrulaması sırasında kullanır ve talebi kullanarakpreferred_username
kullanıcı adını önceki bir oturum açmadan ayıklar.
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);
}
}
Daha fazla bilgi edinmek için aşağıdaki kaynaklara bakın:
Bir belirteci etkileşimli olarak almadan önce seçenekleri özelleştirme
Oluşursa AccessTokenNotAvailableException , yeni bir örneğinde aşağıdaki yöntemlerle yeni identity bir sağlayıcı erişim belirteci isteği için ek parametreleri bir InteractiveRequestOptionsveya daha fazla kez yönetin:
Web API'si aracılığıyla JSON verilerini alan aşağıdaki örnekte, erişim belirteci kullanılamıyorsa (AccessTokenNotAvailableException oluşturulduysa) yeniden yönlendirme isteğine ek parametreler eklenir:
prompt
olarak ayarlanırlogin
: Kullanıcıyı bu istekte kimlik bilgilerini girmeye zorlar ve çoklu oturum açmayı olumsuzlar.loginHint
olarak ayarlanırpeter@contoso.com
: Kullanıcının oturum açma sayfasınınpeter@contoso.com
kullanıcı adı/e-posta adresi alanını olarak önceden doldurur. Uygulamalar bu parametreyi genellikle yeniden kimlik doğrulaması sırasında kullanır ve talebi kullanarakpreferred_username
kullanıcı adını önceki bir oturum açmadan ayıklar.
try
{
var examples = await Http.GetFromJsonAsync<ExampleType[]>("ExampleAPIMethod");
...
}
catch (AccessTokenNotAvailableException ex)
{
ex.Redirect(requestOptions => {
requestOptions.TryAddAdditionalParameter("prompt", "login");
requestOptions.TryAddAdditionalParameter("loginHint", "peter@contoso.com");
});
}
Yukarıdaki örnekte aşağıdakiler varsayılır:
- Ad alanında API için bir
@using
/using
deyiminin Microsoft.AspNetCore.Components.WebAssembly.Authentication varlığı. HttpClient
olarakHttp
eklendi.
Daha fazla bilgi edinmek için aşağıdaki kaynaklara bakın:
IAccessTokenProvider
kullanırken seçenekleri özelleştirme
kullanırken IAccessTokenProviderbelirteç alma işlemi başarısız olursa, yeni identity bir sağlayıcı erişim belirteci isteği için ek parametreleri aşağıdaki yöntemlerle yeni bir örneğinde InteractiveRequestOptionsbir veya daha fazla kez yönetin:
Kullanıcı için erişim belirteci almayı deneyen aşağıdaki örnekte, belirteç alma girişimi çağrıldığında TryGetToken başarısız olursa oturum açma isteğine ek parametreler eklenir:
prompt
olarak ayarlanırlogin
: Kullanıcıyı bu istekte kimlik bilgilerini girmeye zorlar ve çoklu oturum açmayı olumsuzlar.loginHint
olarak ayarlanırpeter@contoso.com
: Kullanıcının oturum açma sayfasınınpeter@contoso.com
kullanıcı adı/e-posta adresi alanını olarak önceden doldurur. Uygulamalar bu parametreyi genellikle yeniden kimlik doğrulaması sırasında kullanır ve talebi kullanarakpreferred_username
kullanıcı adını önceki bir oturum açmadan ayıklar.
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);
}
Yukarıdaki örnekte aşağıdakiler varsayılır:
- Ad alanında API için bir
@using
/using
deyiminin Microsoft.AspNetCore.Components.WebAssembly.Authentication varlığı. - IAccessTokenProvider olarak
TokenProvider
eklendi.
Daha fazla bilgi edinmek için aşağıdaki kaynaklara bakın:
Özel dönüş URL'si ile oturum kapatma
Aşağıdaki örnek kullanıcının oturumunu günlüğe kaydeder ve kullanıcıyı /goodbye
uç noktaya döndürür:
Navigation.NavigateToLogout("authentication/logout", "goodbye");
Kimlik doğrulaması seçeneklerinden oturum açma yolunu alma
Yapılandırılan oturum açma yolunu uygulamasından RemoteAuthenticationOptionsalın:
var loginPath =
RemoteAuthOptions.Get(Options.DefaultName).AuthenticationPaths.LogInPath;
Yukarıdaki örnekte aşağıdakiler varsayılır:
- Aşağıdaki ad alanında API için bir
@using
/using
deyiminin varlığı: IOptionsSnapshot<RemoteAuthenticationOptions<ApiAuthorizationProviderOptions>>
olarakRemoteAuthOptions
eklendi.
Özel AuthorizationMessageHandler
sınıf
Bu bölümdeki bu kılavuz, uygulamanın temel URI'sinde olmayan URI'lere giden istekte bulunan istemci uygulamaları için önerilir.
Aşağıdaki örnekte, özel bir sınıf için olarak DelegatingHandler HttpClientkullanılmak üzere genişletirAuthorizationMessageHandler. ConfigureHandler bir erişim belirteci kullanarak giden HTTP isteklerini yetkilendirmek için bu işleyiciyi yapılandırıyor. Erişim belirteci yalnızca yetkili URL'lerden en az biri istek URI'sinin (HttpRequestMessage.RequestUri) temeliyse eklenir.
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" ]);
}
}
Önceki kodda kapsamlar example.read
ve example.write
genel örnekler, belirli bir sağlayıcı için geçerli kapsamları yansıtmak üzere tasarlanmamıştır.
Program
dosyasında, CustomAuthorizationMessageHandler
geçici bir hizmet olarak kaydedilir ve adlandırılmış HttpClientbir tarafından yapılan giden HttpResponseMessage örnekler için olarak DelegatingHandler yapılandırılır.
Aşağıdaki örnekte, HttpClientFactoryServiceCollectionExtensions.AddHttpClient içindeki Microsoft.Extensions.Httpbir uzantıdır. Paketi, henüz başvurmayan bir uygulamaya ekleyin.
Not
.NET uygulamalarına paket ekleme hakkında yönergeler için, Paket tüketimi iş akışında (NuGet belgeleri) paketleri yüklemek ve yönetmek altındaki makalelere bakın. NuGet.org'da doğru paket sürümlerini onaylayın.
builder.Services.AddTransient<CustomAuthorizationMessageHandler>();
builder.Services.AddHttpClient("WebAPI",
client => client.BaseAddress = new Uri("https://api.contoso.com/v1.0"))
.AddHttpMessageHandler<CustomAuthorizationMessageHandler>();
Not
Yukarıdaki örnekte , CustomAuthorizationMessageHandler
DelegatingHandler için AddHttpMessageHandlergeçici bir hizmet olarak kaydedilir. kendi DI kapsamlarını yöneten için IHttpClientFactorygeçici kayıt önerilir. Daha fazla bilgi edinmek için aşağıdaki kaynaklara bakın:
Proje şablonunu temel alan barındırılan Blazor Blazor WebAssembly bir çözüm için (IWebAssemblyHostEnvironment.BaseAddressnew Uri(builder.HostEnvironment.BaseAddress)
) öğesine HttpClient.BaseAddressatanır.
Yapılandırılan HttpClient , deseni kullanarak try-catch
yetkili isteklerde bulunmak için kullanılır. İstemcinin (Microsoft.Extensions.Http
paket) ile CreateClient oluşturulduğu yerde, HttpClient sunucu API'sine istekte bulunurken erişim belirteçlerini içeren örnekler sağlanır. İstek URI'si, aşağıdaki örnekteExampleAPIMethod
() olduğu gibi göreli bir URI ise, istemci uygulamasının BaseAddress isteği ne zaman yaptığı ile birleştirilir:
@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();
}
}
}
Yapılandırmak AuthorizationMessageHandler
AuthorizationMessageHandler , yöntemini kullanarak yetkili URL'ler, kapsamlar ve bir dönüş URL'si ConfigureHandler ile yapılandırılabilir. ConfigureHandler bir erişim belirteci kullanarak giden HTTP isteklerini yetkilendirmek için işleyiciyi yapılandırıyor. Erişim belirteci yalnızca yetkili URL'lerden en az biri istek URI'sinin (HttpRequestMessage.RequestUri) temeliyse eklenir. İstek URI'si göreli bir URI ise, ile BaseAddressbirleştirilir.
Aşağıdaki örnekte dosyasında AuthorizationMessageHandler bir HttpClient Program
yapılandırılır:
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")
});
Önceki kodda kapsamlar example.read
ve example.write
genel örnekler, belirli bir sağlayıcı için geçerli kapsamları yansıtmak üzere tasarlanmamıştır.
Proje şablonunu IWebAssemblyHostEnvironment.BaseAddresstemel alan barındırılan Blazor Blazor WebAssembly bir çözüm için aşağıdakilere atanır:
- HttpClient.BaseAddress ( ).
new Uri(builder.HostEnvironment.BaseAddress)
- Dizinin URL'si
authorizedUrls
.
Yazılı HttpClient
Tek bir sınıf içindeki tüm HTTP ve belirteç alma sorunlarını işleyen, türü belirlenmiş bir istemci tanımlanabilir.
WeatherForecastClient.cs
:
using System.Net.Http.Json;
using Microsoft.AspNetCore.Components.WebAssembly.Authentication;
using static {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>();
}
}
Yukarıdaki örnekte türü, WeatherForecast
hava durumu tahmin verilerini tutan statik bir sınıftır. Yer {ASSEMBLY NAME}
tutucu, uygulamanın derleme adıdır (örneğin, using static BlazorSample.Data;
).
Aşağıdaki örnekte, HttpClientFactoryServiceCollectionExtensions.AddHttpClient içindeki Microsoft.Extensions.Httpbir uzantıdır. Paketi, henüz başvurmayan bir uygulamaya ekleyin.
Not
.NET uygulamalarına paket ekleme hakkında yönergeler için, Paket tüketimi iş akışında (NuGet belgeleri) paketleri yüklemek ve yönetmek altındaki makalelere bakın. NuGet.org'da doğru paket sürümlerini onaylayın.
Program
dosyasında:
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>();
Proje şablonunu temel alan barındırılan Blazor Blazor WebAssembly bir çözüm için (IWebAssemblyHostEnvironment.BaseAddressnew Uri(builder.HostEnvironment.BaseAddress)
) öğesine HttpClient.BaseAddressatanır.
Hava durumu verilerini getiren bir bileşende:
@inject WeatherForecastClient Client
...
protected override async Task OnInitializedAsync()
{
forecasts = await Client.GetForecastAsync();
}
İşleyiciyi HttpClient
yapılandırma
İşleyici, giden HTTP istekleri için ile ConfigureHandler daha fazla yapılandırılabilir.
Aşağıdaki örnekte, HttpClientFactoryServiceCollectionExtensions.AddHttpClient içindeki Microsoft.Extensions.Httpbir uzantıdır. Paketi, henüz başvurmayan bir uygulamaya ekleyin.
Not
.NET uygulamalarına paket ekleme hakkında yönergeler için, Paket tüketimi iş akışında (NuGet belgeleri) paketleri yüklemek ve yönetmek altındaki makalelere bakın. NuGet.org'da doğru paket sürümlerini onaylayın.
Program
dosyasında:
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" }));
Önceki kodda kapsamlar example.read
ve example.write
genel örnekler, belirli bir sağlayıcı için geçerli kapsamları yansıtmak üzere tasarlanmamıştır.
Proje şablonunu IWebAssemblyHostEnvironment.BaseAddresstemel alan barındırılan Blazor Blazor WebAssembly bir çözüm için aşağıdakilere atanır:
- HttpClient.BaseAddress ( ).
new Uri(builder.HostEnvironment.BaseAddress)
- Dizinin URL'si
authorizedUrls
.
Güvenli bir varsayılan istemciye sahip bir uygulamada kimliği doğrulanmamış veya yetkisiz web API'si istekleri
Normalde güvenli bir varsayılan HttpClient kullanan bir uygulama, adlandırılmış HttpClientbir yapılandırarak kimliği doğrulanmamış veya yetkisiz web API'leri istekleri de yapabilir.
Aşağıdaki örnekte, HttpClientFactoryServiceCollectionExtensions.AddHttpClient içindeki Microsoft.Extensions.Httpbir uzantıdır. Paketi, henüz başvurmayan bir uygulamaya ekleyin.
Not
.NET uygulamalarına paket ekleme hakkında yönergeler için, Paket tüketimi iş akışında (NuGet belgeleri) paketleri yüklemek ve yönetmek altındaki makalelere bakın. NuGet.org'da doğru paket sürümlerini onaylayın.
Program
dosyasında:
builder.Services.AddHttpClient("WebAPI.NoAuthenticationClient",
client => client.BaseAddress = new Uri("https://api.contoso.com/v1.0"));
Proje şablonunu temel alan barındırılan Blazor Blazor WebAssembly bir çözüm için (IWebAssemblyHostEnvironment.BaseAddressnew Uri(builder.HostEnvironment.BaseAddress)
) öğesine HttpClient.BaseAddressatanır.
Önceki kayıt, mevcut güvenli varsayılan HttpClient kayda ek olarak yapılır.
Bir bileşen, kimliği doğrulanmamış veya yetkisiz isteklerde bulunmak için öğesini (Microsoft.Extensions.Http
paketinden IHttpClientFactory ) oluştururHttpClient:
@inject IHttpClientFactory ClientFactory
...
@code {
protected override async Task OnInitializedAsync()
{
var client = ClientFactory.CreateClient("WebAPI.NoAuthenticationClient");
var examples = await client.GetFromJsonAsync<ExampleType[]>(
"ExampleNoAuthentication");
...
}
}
Not
Yukarıdaki örnekte sunucu API'sindeki ExampleNoAuthenticationController
denetleyici özniteliğiyle [Authorize]
işaretlenmemiştir.
Varsayılan HttpClient örnek olarak güvenli istemci mi yoksa güvenli olmayan bir istemci mi kullanılacağına karar geliştiriciye bağlı. Bu kararı vermenin bir yolu, uygulamanın iletişimde olduğu kimliği doğrulanmış ve kimliği doğrulanmamış uç noktaların sayısını göz önünde bulundurmaktır. Uygulamanın isteklerinin çoğu API uç noktalarının güvenliğini sağlamaksa, varsayılan olarak kimliği doğrulanmış HttpClient örneği kullanın. Aksi takdirde, kimliği doğrulanmamış HttpClient örneği varsayılan olarak kaydedin.
kullanmak IHttpClientFactory için alternatif bir yaklaşım anonim uç noktalara kimliği doğrulanmamış erişim için türlenmiş bir istemci oluşturmaktır.
Ek erişim belirteçleri isteme
Erişim belirteçleri çağrılarak IAccessTokenProvider.RequestAccessTokenel ile alınabilir. Aşağıdaki örnekte, varsayılan HttpClientiçin bir uygulama tarafından ek bir kapsam gereklidir. Microsoft Authentication Library (MSAL) örneği kapsamı ile MsalProviderOptions
yapılandırıyor:
Program
dosyasında:
builder.Services.AddMsalAuthentication(options =>
{
...
options.ProviderOptions.AdditionalScopesToConsent.Add("{CUSTOM SCOPE 1}");
options.ProviderOptions.AdditionalScopesToConsent.Add("{CUSTOM SCOPE 2}");
}
{CUSTOM SCOPE 1}
Yukarıdaki örnekteki ve {CUSTOM SCOPE 2}
yer tutucuları özel kapsamlardır.
Not
AdditionalScopesToConsent bir kullanıcı Microsoft Azure'da kayıtlı bir uygulamayı ilk kez kullandığında Microsoft Entra Id onay kullanıcı arabirimi aracılığıyla Microsoft Graph için temsilci kullanıcı izinleri sağlayamaz. Daha fazla bilgi için bkz . ASP.NET Core Blazor WebAssemblyile Graph API'sini kullanma.
yöntemi, IAccessTokenProvider.RequestAccessToken bir uygulamanın belirli bir kapsam kümesiyle erişim belirteci sağlamasına olanak tanıyan bir aşırı yükleme sağlar.
Bir Razor bileşende:
@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}
Yukarıdaki örnekteki ve {CUSTOM SCOPE 2}
yer tutucuları özel kapsamlardır.
AccessTokenResult.TryGetToken Döndürür:
true
token
ile birlikte kullanın.false
belirteci alınmazsa.
Çıkış Noktaları Arası Kaynak Paylaşma (CORS)
CORS isteklerinde kimlik bilgileri (yetkilendirme tanımlama bilgileri/üst bilgileri) gönderirken, Authorization
üst bilgi cors ilkesi tarafından izin verilmelidir.
Aşağıdaki ilke şunlar için yapılandırmayı içerir:
- İstek çıkış noktaları (
http://localhost:5000
,https://localhost:5001
). - Herhangi bir yöntem (fiil).
Content-Type
veAuthorization
üst bilgileri seçin. Özel üst bilgi (örneğin,x-custom-header
) izin vermek için çağrısı WithHeadersyaparken üst bilgiyi listeleyin.- İstemci tarafı JavaScript kodu tarafından ayarlanan kimlik bilgileri (
credentials
özelliği olarakinclude
ayarlanır).
app.UseCors(policy =>
policy.WithOrigins("http://localhost:5000", "https://localhost:5001")
.AllowAnyMethod()
.WithHeaders(HeaderNames.ContentType, HeaderNames.Authorization,
"x-custom-header")
.AllowCredentials());
Proje şablonunu temel alan barındırılan BlazorBlazor WebAssembly bir çözüm, istemci ve sunucu uygulamaları için aynı temel adresi kullanır. İstemci uygulamasının URI'sine HttpClient.BaseAddress builder.HostEnvironment.BaseAddress
ayarlanır. Barındırılan Blazor çözümün varsayılan yapılandırmasında CORS yapılandırması gerekli değildir. Sunucu projesi tarafından barındırılan ve sunucu uygulamasının temel adresini paylaşmayan ek istemci uygulamaları, sunucu projesinde CORS yapılandırması gerektirir.
Daha fazla bilgi için bkz . ASP.NET Core'da Çıkış Noktaları Arası İstekleri (CORS) etkinleştirme ve örnek uygulamanın HTTP İstek Sınayıcısı bileşeni (Components/HTTPRequestTester.razor
).
Belirteç isteği hatalarını işleme
Tek sayfalı bir uygulama (SPA) OpenID Connect (OIDC) kullanarak bir kullanıcının kimliğini doğruladığında, kimlik doğrulama durumu SPA içinde ve Sağlayıcıda Identity (IP) kullanıcının kimlik bilgilerini sağlamasının bir sonucu olarak ayarlanan bir oturum cookie biçiminde yerel olarak korunur.
IP'nin kullanıcı için yaydığı belirteçler genellikle kısa süreler için geçerlidir ve bu nedenle istemci uygulamasının düzenli olarak yeni belirteçleri getirmesi gerekir. Aksi takdirde, verilen belirteçlerin süresi dolduktan sonra kullanıcı oturumu kapatılır. Çoğu durumda OIDC istemcileri, IP içinde tutulan kimlik doğrulama durumu veya "oturum" sayesinde kullanıcının yeniden kimlik doğrulamasına gerek kalmadan yeni belirteçler sağlar.
Bazı durumlarda istemci kullanıcı etkileşimi olmadan belirteç alamaz, örneğin, herhangi bir nedenden dolayı kullanıcının IP'den açıkça oturumu kapattığı durumlar olabilir. Bu senaryo, bir kullanıcı ziyaret https://login.microsoftonline.com
edip oturumu kapatıyorsa oluşur. Bu senaryolarda uygulama kullanıcının oturumunu kapattığını hemen bilmez. İstemcinin tuttuğu belirteçler artık geçerli olmayabilir. Ayrıca istemci, geçerli belirtecin süresi dolduktan sonra kullanıcı etkileşimi olmadan yeni bir belirteç sağlayamaz.
Bu senaryolar belirteç tabanlı kimlik doğrulamasına özgü değildir. BUNLAR SPA'ların doğasının bir parçasıdır. Kimlik doğrulaması cookie kaldırılırsa tanımlama bilgilerini kullanan bir SPA da sunucu API'sini çağıramazsınız.
Bir uygulama korumalı kaynaklara API çağrıları gerçekleştirdiğinde aşağıdakilere dikkat etmeniz gerekir:
- API'yi çağırmak üzere yeni bir erişim belirteci sağlamak için kullanıcının yeniden kimlik doğrulaması gerekebilir.
- İstemcinin geçerli gibi görünen bir belirteci olsa bile, belirteç kullanıcı tarafından iptal edildiğinden sunucu çağrısı başarısız olabilir.
Uygulama belirteç istediğinde iki olası sonuç vardır:
- İstek başarılı olur ve uygulamanın geçerli bir belirteci vardır.
- İstek başarısız olur ve uygulamanın yeni bir belirteç almak için kullanıcının kimliğini yeniden doğrulaması gerekir.
Belirteç isteği başarısız olduğunda, yeniden yönlendirme gerçekleştirmeden önce herhangi bir geçerli durumu kaydetmek isteyip istemediğinize karar vermeniz gerekir. Artan karmaşıklık düzeyleriyle durumu depolamak için çeşitli yaklaşımlar vardır:
- Geçerli sayfa durumunu oturum depolama alanında depolayın.
OnInitializedAsync
Yaşam döngüsü yöntemi ()OnInitializedAsync sırasında devam etmeden önce durumun geri yüklenip yüklenmediğini denetleyin. - Bir sorgu dizesi parametresi ekleyin ve bunu uygulamaya daha önce kaydedilen durumu yeniden nemlendirmesi gerektiğini belirten bir yol olarak kullanın.
- Diğer öğelerle çakışma riskini göze almadan verileri oturum depolama alanında depolamak için benzersiz tanımlayıcıya sahip bir sorgu dizesi parametresi ekleyin.
Oturum depolama ile kimlik doğrulama işleminden önce uygulama durumunu kaydetme
Aşağıdaki örnekte şunların nasıl yapılacağını gösterilmektedir:
- Oturum açma sayfasına yeniden yönlendirmeden önce durumu koruyun.
- Sorgu dizesi parametresini kullanarak kimlik doğrulamasından sonra önceki durumu kurtarın.
...
@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; }
}
}
Oturum depolama ve durum kapsayıcısı ile kimlik doğrulama işleminden önce uygulama durumunu kaydetme
Kimlik doğrulama işlemi sırasında, tarayıcı IP'ye yeniden yönlendirilmeden önce uygulama durumunu kaydetmek istediğiniz durumlar vardır. Durum kapsayıcısı kullanırken ve kimlik doğrulaması başarılı olduktan sonra durumu geri yüklemek istediğinizde bu durum söz konusu olabilir. Uygulamaya özgü durumu veya başvuruyu korumak ve kimlik doğrulama işlemi başarıyla tamamlandıktan sonra bu durumu geri yüklemek için özel bir kimlik doğrulama durumu nesnesi kullanabilirsiniz. Aşağıdaki örnekte yaklaşımı gösterilmektedir.
Uygulamada, uygulamanın durum değerlerini tutacak özelliklere sahip bir durum kapsayıcısı sınıfı oluşturulur. Aşağıdaki örnekte kapsayıcı, varsayılan Blazor proje şablonunun Counter
bileşeninin (Counter.razor
) sayaç değerini korumak için kullanılır. Kapsayıcıyı seri hale getirme ve seri durumdan çıkarma yöntemleri tabanlıdır 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;
}
}
Bileşen, Counter
değeri bileşenin dışında tutmak currentCount
için durum kapsayıcısını kullanır:
@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;
}
}
uygulamasından RemoteAuthenticationStatebir ApplicationAuthenticationState
oluşturun. Id
Yerel olarak depolanan durum için tanımlayıcı işlevi görecek bir özellik sağlayın.
ApplicationAuthenticationState.cs
:
using Microsoft.AspNetCore.Components.WebAssembly.Authentication;
public class ApplicationAuthenticationState : RemoteAuthenticationState
{
public string? Id { get; set; }
}
Bileşen (Authentication.razor
) yerel oturum depolamasını kullanarak serileştirme ve seri durumdan çıkarma yöntemleriyle StateContainer
GetStateForLocalStorage
uygulamanın durumunu kaydeder ve geri yükler ve SetStateFromLocalStorage
:Authentication
@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);
}
}
}
}
Bu örnekte kimlik doğrulaması için Microsoft Entra (ME-ID) kullanılır. Program
dosyasında:
ApplicationAuthenticationState
, Microsoft Kimlik Doğrulama Kitaplığı (MSAL)RemoteAuthenticationState
türü olarak yapılandırılır.- Durum kapsayıcısı hizmet kapsayıcısında kayıtlıdır.
builder.Services.AddMsalAuthentication<ApplicationAuthenticationState>(options =>
{
builder.Configuration.Bind("AzureAd", options.ProviderOptions.Authentication);
});
builder.Services.AddSingleton<StateContainer>();
Uygulama yollarını özelleştirme
Kitaplık, Microsoft.AspNetCore.Components.WebAssembly.Authentication
farklı kimlik doğrulama durumlarını temsil etmek için aşağıdaki tabloda gösterilen yolları kullanır.
Rota | Purpose |
---|---|
authentication/login |
Oturum açma işlemini tetikler. |
authentication/login-callback |
Herhangi bir oturum açma işleminin sonucunu işler. |
authentication/login-failed |
Oturum açma işlemi bir nedenle başarısız olduğunda hata iletilerini görüntüler. |
authentication/logout |
Oturumu kapatma işlemini tetikler. |
authentication/logout-callback |
Oturumu kapatma işleminin sonucunu işler. |
authentication/logout-failed |
Oturum kapatma işlemi bir nedenle başarısız olduğunda hata iletilerini görüntüler. |
authentication/logged-out |
Kullanıcının oturumunu başarıyla kapattığını gösterir. |
authentication/profile |
Kullanıcı profilini düzenlemek için bir işlem tetikler. |
authentication/register |
Yeni bir kullanıcı kaydetmek için bir işlemi tetikler. |
Önceki tabloda gösterilen yollar aracılığıyla RemoteAuthenticationOptions<TRemoteAuthenticationProviderOptions>.AuthenticationPathsyapılandırılabilir. Özel yollar sağlamak için seçenekleri ayarlarken, uygulamanın her yolu işleyen bir yolu olduğunu onaylayın.
Aşağıdaki örnekte, tüm yollara ön ek eklenmiştir /security
.
Authentication
bileşen (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; }
}
Program
dosyasında:
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";
});
Gereksinim tamamen farklı yolları çağırıyorsa, yolları daha önce açıklandığı gibi ayarlayın ve açık bir eylem parametresiyle işleyin RemoteAuthenticatorView :
@page "/register"
<RemoteAuthenticatorView Action="RemoteAuthenticationActions.Register" />
Bunu yapmayı seçerseniz kullanıcı arabirimini farklı sayfalara bölmenize izin verilir.
Kimlik doğrulama kullanıcı arabirimini özelleştirme
RemoteAuthenticatorView her kimlik doğrulama durumu için varsayılan bir kullanıcı arabirimi parçaları kümesi içerir. Her durum özel RenderFragmentbir geçirilerek özelleştirilebilir. İlk oturum açma işlemi sırasında görüntülenen metni özelleştirmek için aşağıdaki gibi değiştirebilirsiniz RemoteAuthenticatorView .
Authentication
bileşen (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; }
}
aşağıdaki RemoteAuthenticatorView tabloda gösterilen kimlik doğrulama yolu başına kullanılabilecek bir parçaya sahiptir.
Rota | Parça |
---|---|
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> |
Kullanıcıyı özelleştirme
Uygulamaya bağlı kullanıcılar özelleştirilebilir.
Kullanıcıyı yük talebiyle özelleştirme
Aşağıdaki örnekte, uygulamanın kimliği doğrulanmış kullanıcıları kullanıcının kimlik doğrulama yöntemlerinin her biri için bir amr
talep alır. Talep, amr
microsoft identity platformu v1.0 yük taleplerinde belirtecin konusunun kimliğinin nasıl doğrulandığını tanımlar. Örnek, tabanlı RemoteUserAccountbir özel kullanıcı hesabı sınıfı kullanır.
sınıfını genişleten RemoteUserAccount bir sınıf oluşturun. Aşağıdaki örnek, özelliği kullanıcının JSON özellik değerleri dizisine amr
ayarlarAuthenticationMethod
. AuthenticationMethod
, kullanıcının kimliği doğrulandığında çerçeve tarafından otomatik olarak doldurulur.
using System.Text.Json.Serialization;
using Microsoft.AspNetCore.Components.WebAssembly.Authentication;
public class CustomUserAccount : RemoteUserAccount
{
[JsonPropertyName("amr")]
public string[]? AuthenticationMethod { get; set; }
}
kullanıcının içinde CustomUserAccount.AuthenticationMethod
depolanan kimlik doğrulama yöntemlerinden talep oluşturmak için genişleten AccountClaimsPrincipalFactory<TAccount> bir fabrika oluşturun:
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;
}
}
CustomAccountFactory
kullanılan kimlik doğrulama sağlayıcısı için öğesini kaydedin. Aşağıdaki kayıtlardan herhangi biri geçerlidir:
-
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>();
Özel kullanıcı hesabı sınıfına sahip ME-ID güvenlik grupları ve rolleri
ME-ID güvenlik grupları ve ME-ID Yönetici Rolleri ve özel kullanıcı hesabı sınıfıyla çalışan ek bir örnek için bkz. Microsoft Entra Id grupları ve rolleri ile ASP.NET CoreBlazor WebAssembly.
Kimlik doğrulaması ile önceden giriş
Kimlik doğrulaması ve yetkilendirme gerektiren ön kayıt içeriği şu anda desteklenmemektedir. Güvenlik uygulaması konularından birinde yer alan Blazor WebAssembly yönergeleri takip ettikten sonra aşağıdaki yönergeleri kullanarak şu adımları izleyin:
- Yetkilendirme gerektirmeyen prerenders yolları.
- Yetkilendirmenin gerekli olduğu yolları önceden oluşturmaz.
Client Projenin Program
dosyası için ortak hizmet kayıtlarını ayrı bir yönteme ekleyin (örneğin, projede Client bir ConfigureCommonServices
yöntem oluşturun). Yaygın hizmetler, geliştiricinin hem istemci hem de sunucu projeleri tarafından kullanılmak üzere kaydolan hizmetlerdir.
public static void ConfigureCommonServices(IServiceCollection services)
{
services.Add...;
}
Program
dosyasında:
var builder = WebAssemblyHostBuilder.CreateDefault(args);
...
builder.Services.AddScoped( ... );
ConfigureCommonServices(builder.Services);
await builder.Build().RunAsync();
Server Projenin Program
dosyasında aşağıdaki ek hizmetleri kaydedin ve öğesini çağırınConfigureCommonServices
:
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);
Projenin yönteminde Server aşağıdaki ek hizmetleri kaydedin ve öğesini çağırınConfigureCommonServices
:Startup.ConfigureServices
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);
}
Çerçeve sunucusu kimlik doğrulama sağlayıcısı ( ) hakkında Blazor daha fazla bilgi için bkz. ASP.NET Çekirdek Blazor kimlik doğrulaması ve yetkilendirme.ServerAuthenticationStateProvider
Server Projenin dosyasında Etiket Yardımcısı'nı Pages/_Host.cshtml
Component
(<component ... />
) aşağıdakilerle değiştirin:
<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>
Yukarıdaki örnekte:
- Yer
{CLIENT APP ASSEMBLY NAME}
tutucu, istemci uygulamasının derleme adıdır (örneğinBlazorSample.Client
). - Yol kesimi için
/authentication
koşullu denetim:- Kimlik doğrulama yolları için ön kayıttan (
render-mode="WebAssembly"
) kaçınıyor. - Kimlik doğrulaması olmayan yollar için prerenders (
render-mode="WebAssemblyPrerendered"
).
- Kimlik doğrulama yolları için ön kayıttan (
Barındırılan uygulamalar ve üçüncü taraf oturum açma sağlayıcıları için seçenekler
Barındırılan Blazor WebAssembly bir uygulamanın kimliğini doğrulamak ve üçüncü taraf sağlayıcıyla yetkilendirmek için kullanıcının kimliğini doğrulamak için çeşitli seçenekler vardır. Hangisini seçtiğiniz senaryonuza bağlıdır.
Daha fazla bilgi için, bkz. ASP.NET Core'da dış sağlayıcılardan gelen ek talepleri ve belirteçleri kalıcı hale getirme.
Yalnızca korumalı üçüncü taraf API'leri çağırmak için kullanıcıların kimliğini doğrulama
Üçüncü taraf API sağlayıcısında istemci tarafı OAuth akışıyla kullanıcının kimliğini doğrula:
builder.services.AddOidcAuthentication(options => { ... });
Bu senaryoda:
- Uygulamayı barındıran sunucu bir rol oynamaz.
- Sunucudaki API'ler korunamaz.
- Uygulama yalnızca korumalı üçüncü taraf API'leri çağırabilir.
Üçüncü taraf sağlayıcıyla kullanıcıların kimliğini doğrulama ve konak sunucusunda ve üçüncü taraf üzerinde korumalı API'leri çağırma
Üçüncü taraf oturum açma sağlayıcısıyla yapılandırın Identity . Üçüncü taraf API erişimi için gereken belirteçleri alın ve depolayın.
Kullanıcı oturum açtığında, Identity kimlik doğrulama işleminin bir parçası olarak erişim ve yenileme belirteçlerini toplar. Bu noktada, üçüncü taraf API'lere API çağrıları yapmak için kullanılabilecek birkaç yaklaşım vardır.
Üçüncü taraf erişim belirtecini almak için sunucu erişim belirteci kullanma
Sunucu API'sinin uç noktasından üçüncü taraf erişim belirtecini almak için sunucuda oluşturulan erişim belirtecini kullanın. Buradan, üçüncü taraf API kaynaklarını doğrudan istemciden Identity çağırmak için üçüncü taraf erişim belirtecini kullanın.
Bu yaklaşımı önermiyoruz. Bu yaklaşım, üçüncü taraf erişim belirtecinin genel istemci için oluşturulmuş gibi ele alındığını gerektirir. OAuth terimlerinde, gizli dizileri güvenli bir şekilde depolamaya güvenilemediği ve erişim belirteci gizli bir istemci için üretildiği için genel uygulamanın gizli dizisi yoktur. Gizli istemci, gizli dizisi olan ve gizli dizileri güvenli bir şekilde depolayabildiği varsayılan bir istemcidir.
- Üçüncü taraf erişim belirtecine, üçüncü tarafın daha güvenilir bir istemci için belirteci yayması temelinde hassas işlemler gerçekleştirmek için ek kapsamlar verilebilir.
- Benzer şekilde, yenileme belirteçleri güvenilir olmayan bir istemciye verilmemelidir, çünkü bunu yapmak istemciye başka kısıtlamalar getirilmediği sürece sınırsız erişim verir.
Üçüncü taraf API'leri çağırmak için istemciden sunucu API'sine API çağrıları yapma
İstemciden sunucu API'sine bir API çağrısı yapın. Sunucudan, üçüncü taraf API kaynağı için erişim belirtecini alın ve gereken çağrıyı yapın.
Bu yaklaşımı öneririz. Bu yaklaşım, bir üçüncü taraf API'yi çağırmak için sunucuda fazladan bir ağ atlama gerektirir ancak sonuçta daha güvenli bir deneyim elde edersiniz:
- Sunucu yenileme belirteçlerini depolayabilir ve uygulamanın üçüncü taraf kaynaklara erişimini kaybetmediğinden emin olabilir.
- Uygulama, daha hassas izinler içerebilecek sunucudan erişim belirteçlerini sızdıramaz.
OpenID Connect (OIDC) v2.0 uç noktalarını kullanma
Kimlik doğrulama kitaplığı ve Blazor proje şablonları OpenID Connect (OIDC) v1.0 uç noktalarını kullanır. v2.0 uç noktasını kullanmak için JWT Taşıyıcı JwtBearerOptions.Authority seçeneğini yapılandırın. Aşağıdaki örnekte, ME-ID özelliğine Authority bir v2.0
kesim eklenerek v2.0 için yapılandırılır:
using Microsoft.AspNetCore.Authentication.JwtBearer;
...
builder.Services.Configure<JwtBearerOptions>(
JwtBearerDefaults.AuthenticationScheme,
options =>
{
options.Authority += "/v2.0";
});
Alternatif olarak, ayar uygulama ayarları (appsettings.json
) dosyasında yapılabilir:
{
"Local": {
"Authority": "https://login.microsoftonline.com/common/oauth2/v2.0/",
...
}
}
Bir segmenti yetkiliye eklemek, uygulamanın OIDC sağlayıcısı için uygun değilse (me kimliği olmayan sağlayıcılarda olduğu gibi) özelliği doğrudan ayarlayın Authority . özelliğini JwtBearerOptions veya uygulama ayarları dosyasında (appsettings.json
) anahtarıyla Authority
ayarlayın.
Kimlik belirtecindeki taleplerin listesi v2.0 uç noktaları için değişir. Değişikliklerle ilgili Microsoft belgeleri kullanımdan kaldırılmıştır, ancak kimlik belirtecindeki taleplere ilişkin yönergeler kimlik belirteci talep başvurusunda sağlanır.
Bileşenlerde gRPC'yi yapılandırma ve kullanma
Bir Blazor WebAssembly uygulamayı ASP.NET Core gRPC çerçevesini kullanacak şekilde yapılandırmak için:
- Sunucuda gRPC-Web'i etkinleştirin. Daha fazla bilgi için bkz . ASP.NET Core gRPC uygulamalarında gRPC-Web.
- Uygulamanın ileti işleyicisi için gRPC hizmetlerini kaydedin. Aşağıdaki örnekte, uygulamanın yetkilendirme iletisi işleyicisi gRPC öğreticisinden (dosya) hizmeti kullanacak
GreeterClient
şekilde yapılandırılırProgram
.
Not
Prerendering varsayılan olarak s içinde Blazor Web Appetkindir, bu nedenle önce sunucudan sonra istemciden bileşen işlemeyi hesaba aktarmanız gerekir. Yeniden kullanılabilmesi için önceden oluşturulmuş tüm durumların istemciye akması gerekir. Daha fazla bilgi için bkz . Prerender ASP.NET Core Razor bileşenleri.
Not
Ön kayıt, barındırılan Blazor WebAssembly uygulamalarda varsayılan olarak etkindir, bu nedenle önce sunucudan sonra istemciden bileşen işlemeyi hesaba aktarmanız gerekir. Yeniden kullanılabilmesi için önceden oluşturulmuş tüm durumların istemciye akması gerekir. Daha fazla bilgi için bkz . Prerender ve ASP.NET Core Razor bileşenlerini tümleştirme.
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);
});
İstemci uygulamasındaki bir bileşen gRPC istemcisini (Grpc.razor
) kullanarak gRPC çağrıları yapabilir:
@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();
}
}
}
özelliğini kullanmak Status.DebugException
için 2.30.0 veya sonraki bir sürümü kullanın Grpc.Net.Client
.
Daha fazla bilgi için bkz . ASP.NET Core gRPC uygulamalarında gRPC-Web.
AuthenticationService
Uygulamayı değiştirme
Aşağıdaki alt bölümler, nasıl değiştirilmeyi açıklanmaktadır:
- Herhangi bir JavaScript
AuthenticationService
uygulaması. - JavaScript için Microsoft Kimlik Doğrulama Kitaplığı (
MSAL.js
).
Herhangi bir JavaScript AuthenticationService
uygulamasını değiştirme
Özel kimlik doğrulama ayrıntılarınızı işlemek için bir JavaScript kitaplığı oluşturun.
Uyarı
Bu bölümdeki kılavuz, varsayılan RemoteAuthenticationService<TRemoteAuthenticationState,TAccount,TProviderOptions>öğesinin uygulama ayrıntılarıdır. Bu bölümdeki TypeScript kodu özellikle .NET 7'deki ASP.NET Core için geçerlidir ve ASP.NET Core'un gelecek sürümlerinde bildirimde bulunmadan değiştirilebilir.
// .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 };
};
Özgün <script>
etiketi kaldırıp özel kitaplığı yükleyen bir <script>
etiket ekleyerek kitaplığı içeri aktarabilirsiniz. Aşağıdaki örnek, varsayılan <script>
etiketi klasörden adlı CustomAuthenticationService.js
wwwroot/js
bir kitaplığı yükleyen bir etiketle değiştirmeyi gösterir.
wwwroot/index.html
Kapatma </body>
etiketinin Blazor içindeki betikten (_framework/blazor.webassembly.js
) önce:
- <script src="_content/Microsoft.Authentication.WebAssembly.Msal/AuthenticationService.js"></script>
+ <script src="js/CustomAuthenticationService.js"></script>
Daha fazla bilgi için GitHub deposundaki bölümüne bakınAuthenticationService.ts
.dotnet/aspnetcore
Not
.NET başvuru kaynağına yönelik belge bağlantıları genellikle deponun varsayılan dalını yükler ve bu dal .NET'in sonraki sürümü için geçerli geliştirmeyi temsil eder. Belirli bir sürümün etiketini seçmek için Dalları veya etiketleri değiştir açılan listesini kullanın. Daha fazla bilgi için bkz. ASP.NET Core kaynak kodunun sürüm etiketini seçme (dotnet/AspNetCore.Docs #26205).
JavaScript için Microsoft Kimlik Doğrulama Kitaplığı'nı değiştirme (MSAL.js
)
Bir uygulama JavaScript için Microsoft Kimlik Doğrulama Kitaplığı'nın (MSAL.js
)özel bir sürümünü gerektiriyorsa aşağıdaki adımları gerçekleştirin:
- Sistemin en son geliştirici .NET SDK'sı olduğunu onaylayın veya .NET Core SDK'sından en son geliştirici SDK'sını alın ve yükleyin: Yükleyiciler ve İkili Dosyalar. Bu senaryo için iç NuGet akışlarının yapılandırılması gerekli değildir.
- Kaynaktan
dotnet/aspnetcore
ASP.NET Core Oluşturma konusundaki belgeleri izleyerek GitHub deposunu geliştirme için ayarlayın. Çatal oluşturun ve GitHub deposunun ZIP arşivinidotnet/aspnetcore
kopyalayın veya indirin. src/Components/WebAssembly/Authentication.Msal/src/Interop/package.json
dosyasını açın ve istenen sürümünü@azure/msal-browser
ayarlayın. Yayımlanan sürümlerin listesi için npm web sitesini ziyaret edin@azure/msal-browser
ve Sürümler sekmesini seçin.Authentication.Msal
Komutu bir komut kabuğundasrc/Components/WebAssembly/Authentication.Msal/src
komutuylayarn build
klasöründe projeyi oluşturun.- Uygulama sıkıştırılmış varlıklar (Brotli/Gzip) kullanıyorsa dosyayı sıkıştırın
Interop/dist/Release/AuthenticationService.js
. AuthenticationService.js
Oluşturulursa, dosyanın dosyasını ve sıkıştırılmış sürümlerini (.br
.gz
/) klasördenInterop/dist/Release
uygulamanın yayımlanan varlıklarındaki uygulamanınpublish/wwwroot/_content/Microsoft.Authentication.WebAssembly.Msal
klasörüne kopyalayın.
Özel sağlayıcı seçeneklerini geçirme
Verileri temel alınan JavaScript kitaplığına geçirmek için bir sınıf tanımlayın.
Önemli
Sınıfın yapısı, JSON ile seri hale getirildiğinde kitaplığın beklediğiyle System.Text.Jsoneşleşmelidir.
Aşağıdaki örnekte, varsayımsal ProviderOptions
bir özel sağlayıcı kitaplığının beklentileriyle eşleşen özniteliklere sahip JsonPropertyName
bir sınıf gösterilmektedir:
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; }
}
DI sistemindeki sağlayıcı seçeneklerini kaydedin ve uygun değerleri yapılandırın:
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 = "...";
});
Yukarıdaki örnek, normal dize değişmez değerleriyle yeniden yönlendirme URI'lerini ayarlar. Aşağıdaki alternatifler kullanılabilir:
TryCreate kullanarak IWebAssemblyHostEnvironment.BaseAddress:
Uri.TryCreate( $"{builder.HostEnvironment.BaseAddress}authentication/login-callback", UriKind.Absolute, out var redirectUri); options.RedirectUri = redirectUri;
Konak oluşturucu yapılandırması:
options.RedirectUri = builder.Configuration["RedirectUri"];
wwwroot/appsettings.json
:{ "RedirectUri": "https://localhost:5001/authentication/login-callback" }
Ek kaynaklar
ASP.NET Core