Aracılığıyla paylaş


ASP.NET Core sunucu tarafı ve Blazor Web App ek güvenlik senaryoları

Not

Bu, bu makalenin en son sürümü değildir. Geçerli sürüm için bu makalenin .NET 9 sürümüne bakın.

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 9 sürümüne bakın.

Önemli

Bu bilgiler, ticari olarak piyasaya sürülmeden önce önemli ölçüde değiştirilebilen bir yayın öncesi ürünle ilgilidir. Burada verilen bilgilerle ilgili olarak Microsoft açık veya zımni hiçbir garanti vermez.

Geçerli sürüm için bu makalenin .NET 9 sürümüne bakın.

Bu makale, Blazor uygulamasına belirteç geçirme de dahil olmak üzere ek güvenlik senaryoları için Blazor sunucu tarafı yapılandırmasını açıklar.

Not

Bu makaledeki kod örnekleri, .NET 6 veya sonraki sürümlerindeki ASP.NET Core'da desteklenen null atanabilir başvuru türlerini (NTS) ve .NET derleyici null durum statik analizini benimser. .NET 5 veya daha önceki sürümleri hedeflerken, makalenin örneklerinde ?, string?, TodoItem[]?, ve WeatherForecast[]? türlerinden "null türü atamasını" (IEnumerable<GitHubBranch>?) kaldırın.

Belirteçleri sunucu tarafı Blazor uygulamasına geçirme

Bu bölüm Blazor Web App'ler için geçerlidir. Blazor Server için bu makale bölümünün .NET 7 sürümünü görüntüleyin.

Yalnızca Blazor Web App olan bir istemciden web API çağrıları yapmak için erişim belirteçlerini kullanmak istiyorsanız, giden isteklere kullanıcının erişim belirtecini eklemek için uygulamanın nasıl kullanılacağını açıklayan DelegatingHandler bölümüne bakın. Bu bölümdeki aşağıdaki kılavuz, erişim belirteçlerine, yenileme belirteçlerine ve diğer kimlik doğrulama özelliklerine başka amaçlarla sunucu tarafında ihtiyaç duyan geliştiricilere yöneliktir.

Sunucu tarafı kullanımı için Blazor Web App'ler içinde belirteçleri ve diğer kimlik doğrulama özelliklerini kaydetmek üzere IHttpContextAccessor/HttpContext (IHttpContextAccessor, HttpContext) kullanmanızı öneririz. Belirteçler statik sunucu tarafı işleme (statik SSR) veya ön kayıt sırasında elde edilirse etkileşimli HttpContext sunucu işleme sırasında kullanılacak belirteçleri almak için, basamaklı parametre olarak da dahil olmak üzere ' den IHttpContextAccessorbelirteçlerin okunması desteklenir. Ancak, devre kurulduktan sonra kullanıcı kimlik doğrulaması yapsa bile belirteçler güncellenmez, çünkü HttpContext, SignalR bağlantısının başlangıcında yakalanır. Ayrıca, AsyncLocal<T> öğesinin IHttpContextAccessor tarafından kullanılması, HttpContext okuyana kadar yürütme bağlamını kaybetmemeye dikkat etmeniz gerektiği anlamına gelir. Daha fazla bilgi için bkz. IHttpContextAccessor/HttpContext ASP.NET Core Blazor uygulamalarında.

Bir hizmet sınıfında, `Microsoft.AspNetCore.Authentication` ad alanının üyelerine erişin ve `GetTokenAsync` üzerinde `HttpContext` yöntemini ortaya çıkarın. Aşağıdaki örnekte açıklama satırı ile devre dışı bırakılan alternatif bir yaklaşım, üzerinde AuthenticateAsync için HttpContext çağrısı yapmaktır. Döndürülen AuthenticateResult.Properties için GetTokenValue öğesini çağırın.

using Microsoft.AspNetCore.Authentication;

public class AuthenticationProcessor(IHttpContextAccessor httpContextAccessor)
{
    public async Task<string?> GetAccessToken()
    {
        if (httpContextAccessor.HttpContext is null)
        {
            throw new Exception("HttpContext not available");
        }

        // Approach 1: Call 'GetTokenAsync'
        var accessToken = await httpContextAccessor.HttpContext
            .GetTokenAsync("access_token");

        // Approach 2: Authenticate the user and call 'GetTokenValue'
        /*
        var authResult = await httpContextAccessor.HttpContext.AuthenticateAsync();
        var accessToken = authResult?.Properties?.GetTokenValue("access_token");
        */

        return accessToken;
    }
}

Hizmet, sunucu projesinin Program dosyasına kaydedilir:

builder.Services.AddScoped<AuthenticationProcessor>();

AuthenticationProcessor sunucu tarafı hizmetlerine, örneğin önceden yapılandırılmış bir DelegatingHandler için bir HttpClient'e eklenebilir. Aşağıdaki örnek yalnızca tanıtım amaçlıdır veya AuthenticationProcessor hizmetinde özel işlem gerçekleştirmeniz gerektiğinde kullanılabilir, çünkü IHttpContextAccessor ekleyerek belirteci doğrudan alabilir ve dış web API'lerini çağırabilirsiniz (web API'lerini doğrudan çağırmak için IHttpContextAccessor kullanımı hakkında daha fazla bilgi için Web API çağrıları için belirteç işleyicisi kullanma bölümüne bakın).

using System.Net.Http.Headers;

public class TokenHandler(AuthenticationProcessor authProcessor) : 
    DelegatingHandler
{
    protected override async Task<HttpResponseMessage> SendAsync(
        HttpRequestMessage request, CancellationToken cancellationToken)
    {
        var accessToken = authProcessor.GetAccessToken();

        request.Headers.Authorization =
            new AuthenticationHeaderValue("Bearer", accessToken);

        return await base.SendAsync(request, cancellationToken);
    }
}

Belirteç işleyicisi kaydedilir ve Program dosyasında ad verilmiş bir HTTP istemcisi için bir yetkilendirme işleyicisi olarak görev yapar.

builder.Services.AddHttpContextAccessor();

builder.Services.AddScoped<TokenHandler>();

builder.Services.AddHttpClient("ExternalApi",
      client => client.BaseAddress = new Uri(builder.Configuration["ExternalApiUri"] ?? 
          throw new Exception("Missing base address!")))
      .AddHttpMessageHandler<TokenHandler>();

Dikkat

Belirteçlerin hiçbir zaman istemci ( .Client proje) tarafından iletilmediğinden ve işlenmediğinden emin olun; örneğin, Etkileşimli Otomatik işlemeyi benimseyen ve istemcide veya istemci tarafı hizmeti tarafından işlenen bir bileşende. İstemcinin istekleri belirteçlerle işlemek için her zaman sunucuyu (proje) çağırmasını sağlayın. Belirteçler ve diğer kimlik doğrulama verileri hiçbir zaman sunucudan ayrılmamalıdır.

Etkileşimli Otomatik bileşenler için, erişim belirteçlerinin ve diğer kimlik doğrulama özelliklerinin sunucuda nasıl bırakıldığına ilişkin ASP.NET Çekirdek Blazorkimlik doğrulaması ve yetkilendirme bölümüne bakın. Ayrıca, benzer bir çağrı yapısına sahip olan ve OIDC sağlayıcıları için OpenID Connect (OIDC) ile ASP.NET Core'u Blazor Web App güvenli hale getirme ile Microsoft Web için Microsoft Entra ID ile ASP.NET Core'u Blazor Web App güvenli hale getirme bölümünde açıklanan "Frontend için Backend" (BFF) desenini benimsemeyi göz önünde bulundurun.

Web API çağrıları için belirteç işleyicisi kullanma

Aşağıdaki yaklaşım, özellikle dış web API uygulamalarına web API çağrıları yapmak için giden isteklere kullanıcının erişim belirtecini eklemeyi hedeflemektedir. Yaklaşım, genel Etkileşimli Sunucu işlemeyi benimseyen bir Blazor Web App için gösterilir, ancak genel Etkileşimli Otomatik işleme modunu benimseyenler için Blazor Web Appde aynı genel yaklaşım geçerlidir. Göz önünde bulundurulması gereken önemli kavram, HttpContext'a erişimin IHttpContextAccessor kullanılarak yalnızca sunucuda gerçekleştirilmesidir.

BlazorWebAppOidc ve BlazorWebAppOidcServer örnek uygulamalarına (.NET 8 veya üzeri) bakın. Bu bölümdeki yönergelerin bir gösterimi için Blazor örnek GitHub deposundaki Örnekler, Entra'ya özgü paketler kullanmadan Microsoft Entra ile genel etkileşimli işleme modunu ve OIDC kimlik doğrulamasını benimser. Örneklerde, JWT erişim belirteciyle güvenli bir web API'sini nasıl çağırabileceğiniz gösterilmektedir.

Microsoft Entra ID için Microsoft Identity Web paketlerine sahip Microsoft kimlik platformu, Blazor Web App içinden web API'lerini çağırmak için otomatik belirteç yönetimi ve yenileme ile bir API sunar. Daha fazla bilgi için, Blazor Web App bölümüne ve bakın.

Kullanıcının erişim belirtecini giden isteklere eklemek için alt sınıf DelegatingHandler . Belirteç işleyicisi yalnızca sunucuda yürütülür, bu nedenle kullanmak HttpContext güvenlidir.

TokenHandler.cs:

using System.Net.Http.Headers;
using Microsoft.AspNetCore.Authentication;

public class TokenHandler(IHttpContextAccessor httpContextAccessor) : 
    DelegatingHandler
{
    protected override async Task<HttpResponseMessage> SendAsync(
        HttpRequestMessage request, CancellationToken cancellationToken)
    {
        if (httpContextAccessor.HttpContext is null)
        {
            throw new Exception("HttpContext not available");
        }

        var accessToken = await httpContextAccessor.HttpContext.GetTokenAsync("access_token");

        if (accessToken is null)
        {
            throw new Exception("No access token");
        }

        request.Headers.Authorization =
            new AuthenticationHeaderValue("Bearer", accessToken);

        return await base.SendAsync(request, cancellationToken);
    }
}

Not

Bir AuthenticationStateProvider aracılığıyla DelegatingHandler erişim yönergeleri için giden istek ara yazılımdaki erişim AuthenticationStateProvider bölümüne bakın.

Projenin Program dosyasında, belirteç işleyicisi (TokenHandler) kapsamlı bir hizmet olarak kaydedilir ve ile AddHttpMessageHandler mesaj işleyicisi olarak belirtilir.

Aşağıdaki örnekte, {HTTP CLIENT NAME} yer tutucu adı, HttpClient{BASE ADDRESS} yer tutucu ise web API'sinin temel adres URI'sidir. hakkında AddHttpContextAccessordaha fazla bilgi için bkz. ASP.NET Core Blazor uygulamalarında IHttpContextAccessor/HttpContext.

Program.cs içinde:

builder.Services.AddHttpContextAccessor();

builder.Services.AddScoped<TokenHandler>();

builder.Services.AddHttpClient("{HTTP CLIENT NAME}",
      client => client.BaseAddress = new Uri("{BASE ADDRESS}"))
      .AddHttpMessageHandler<TokenHandler>();

Örnek:

builder.Services.AddScoped<TokenHandler>();

builder.Services.AddHttpClient("ExternalApi",
      client => client.BaseAddress = new Uri("https://localhost:7277"))
      .AddHttpMessageHandler<TokenHandler>();

Yapılandırma ile HTTP istemci temel adresini builder.Configuration["{CONFIGURATION KEY}"] arasında, {CONFIGURATION KEY} yer tutucu yapılandırma anahtarı olarak kullanılacak şekilde sağlayabilirsiniz:

new Uri(builder.Configuration["ExternalApiUri"] ?? throw new IOException("No URI!"))

appsettings.json içinde, ExternalApiUri öğesini belirtin. Aşağıdaki örnek, değeri dış web API'sinin https://localhost:7277localhost adresine ayarlar:

"ExternalApiUri": "https://localhost:7277"

Bu noktada, bir bileşen tarafından oluşturulan bir HttpClient güvenli web API'si istekleri yapabilir. Aşağıdaki örnekte, {REQUEST URI} bağıl istek URI'si ve {HTTP CLIENT NAME} yer tutucu, HttpClient'inin adıdır.

using var request = new HttpRequestMessage(HttpMethod.Get, "{REQUEST URI}");
var client = ClientFactory.CreateClient("{HTTP CLIENT NAME}");
using var response = await client.SendAsync(request);

Örnek:

using var request = new HttpRequestMessage(HttpMethod.Get, "/weather-forecast");
var client = ClientFactory.CreateClient("ExternalApi");
using var response = await client.SendAsync(request);

Blazor için ek özellikler planlanmaktadır, Access AuthenticationStateProvider giden istek ara yazılımında (dotnet/aspnetcore #52379) izlenmektedir. Etkileşimli Sunucu modunda (dotnet/aspnetcore #52390) HttpClient'a Erişim Belirteci sağlama sorunu, gelişmiş kullanım örnekleri için yararlı tartışmalar ve olası geçici çözüm stratejileri içeren kapalı bir sorundur.

Sunucu tarafı Razor uygulamasındaki bileşenlerin dışında Blazor bulunan belirteçler, bu bölümde açıklanan yaklaşımla bileşenlere geçirilebilir. Bu bölümdeki örnek, uygulamaya erişim, yenileme ve istek sahteciliği önleme (XSRF) belirteci belirteçlerinin geçirilmesine Blazor odaklanır, ancak yaklaşım diğer HTTP bağlam durumu için geçerlidir.

Not

XSRF belirtecinin Razor bileşenlerine geçirilmesi, bileşenlerin doğrulama gerektiren POST işlemlerinde veya diğer doğrulama gerektiren uç noktalara Identity gönderilmesinde kullanışlıdır. Uygulamanız yalnızca erişim ve yenileme belirteçleri gerektiriyorsa, aşağıdaki örnekten XSRF belirteç kodunu kaldırabilirsiniz.

Normal Razor Sayfalar veya MVC uygulamasıyla yaptığınız gibi uygulamanın kimliğini doğrula. Belirteçleri sağlayın ve kimlik doğrulamasına cookiekaydedin.

Program dosyasında:

using Microsoft.AspNetCore.Authentication.OpenIdConnect;
using Microsoft.IdentityModel.Protocols.OpenIdConnect;

...

builder.Services.Configure<OpenIdConnectOptions>(
    OpenIdConnectDefaults.AuthenticationScheme, options =>
{
    options.ResponseType = OpenIdConnectResponseType.Code;
    options.SaveTokens = true;
    options.Scope.Add(OpenIdConnectScope.OfflineAccess);
});

Startup.cs içinde:

using Microsoft.AspNetCore.Authentication.OpenIdConnect;
using Microsoft.IdentityModel.Protocols.OpenIdConnect;

...

services.Configure<OpenIdConnectOptions>(
    OpenIdConnectDefaults.AuthenticationScheme, options =>
{
    options.ResponseType = OpenIdConnectResponseType.Code;
    options.SaveTokens = true;
    options.Scope.Add(OpenIdConnectScope.OfflineAccess);
});

Startup.cs içinde:

using Microsoft.AspNetCore.Authentication.OpenIdConnect;
using Microsoft.IdentityModel.Protocols.OpenIdConnect;

...

services.Configure<OpenIdConnectOptions>(AzureADDefaults.OpenIdScheme, options =>
{
    options.ResponseType = OpenIdConnectResponseType.Code;
    options.SaveTokens = true;
    options.Scope.Add(OpenIdConnectScope.OfflineAccess);
});

İsteğe bağlı olarak, ek kapsamlar options.Scope.Add("{SCOPE}"); ile eklenir; burada {SCOPE} yer tutucu, eklenecek ek kapsamdır.

Uygulama içinde, bağımlılık ekleme (DI) yoluyla belirteçleri çözümlemek için kullanılabilecek scoped türünde bir belirteç sağlayıcı hizmeti tanımlayın.

TokenProvider.cs:

public class TokenProvider
{
    public string? AccessToken { get; set; }
    public string? RefreshToken { get; set; }
    public string? XsrfToken { get; set; }
}

Program dosyasına şu hizmetler için hizmetler ekleyin:

  • IHttpClientFactory: Erişim belirteci olan bir WeatherForecastService sunucu API'sinden hava durumu verileri alan bir sınıfta kullanılır.
  • TokenProvider: Erişim ve yenileme belirteçlerini tutar.
builder.Services.AddHttpClient();
builder.Services.AddScoped<TokenProvider>();

Startup.ConfigureServices'in Startup.cs içinde, için hizmetler ekleyin:

  • IHttpClientFactory: Erişim belirteci olan bir WeatherForecastService sunucu API'sinden hava durumu verileri alan bir sınıfta kullanılır.
  • TokenProvider: Erişim ve yenileme belirteçlerini tutar.
services.AddHttpClient();
services.AddScoped<TokenProvider>();

Erişim ve yenileme belirteçleriyle ilk uygulama durumunu geçirmek için bir sınıf tanımlayın.

InitialApplicationState.cs:

public class InitialApplicationState
{
    public string? AccessToken { get; set; }
    public string? RefreshToken { get; set; }
    public string? XsrfToken { get; set; }
}

Pages/_Host.cshtml dosyasında bir InitialApplicationState örneği oluşturun ve bunu uygulamaya parametre olarak geçirin.

Pages/_Layout.cshtml dosyasında bir InitialApplicationState örneği oluşturun ve bunu uygulamaya parametre olarak geçirin.

Pages/_Host.cshtml dosyasında bir InitialApplicationState örneği oluşturun ve bunu uygulamaya parametre olarak geçirin.

@using Microsoft.AspNetCore.Authentication
@inject Microsoft.AspNetCore.Antiforgery.IAntiforgery Xsrf

...

@{
    var tokens = new InitialApplicationState
    {
        AccessToken = await HttpContext.GetTokenAsync("access_token"),
        RefreshToken = await HttpContext.GetTokenAsync("refresh_token"),
        XsrfToken = Xsrf.GetAndStoreTokens(HttpContext).RequestToken
    };
}

<component ... param-InitialState="tokens" ... />

() bileşeninde AppApp.razorhizmeti çözümleyin ve parametresindeki verilerle başlatın:

@inject TokenProvider TokenProvider

...

@code {
    [Parameter]
    public InitialApplicationState? InitialState { get; set; }

    protected override Task OnInitializedAsync()
    {
        TokenProvider.AccessToken = InitialState?.AccessToken;
        TokenProvider.RefreshToken = InitialState?.RefreshToken;
        TokenProvider.XsrfToken = InitialState?.XsrfToken;

        return base.OnInitializedAsync();
    }
}

Not

Önceki örnekte TokenProvider'ye ilk durumu atamanın alternatifi, verileri uygulama genelinde kullanılmak üzere OnInitializedAsync kapsamlı bir hizmet içine kopyalamaktır.

Uygulama için Microsoft.AspNet.WebApi.Client NuGet paketine bir paket başvurusu 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.

Güvenli API talebinde bulunan hizmete belirteç sağlayıcısını enjekte edin ve API talebi için belirteci alın.

WeatherForecastService.cs:

using System;
using System.Net.Http;
using System.Threading.Tasks;

public class WeatherForecastService
{
    private readonly HttpClient http;
    private readonly TokenProvider tokenProvider;

    public WeatherForecastService(IHttpClientFactory clientFactory, 
        TokenProvider tokenProvider)
    {
        http = clientFactory.CreateClient();
        this.tokenProvider = tokenProvider;
    }

    public async Task<WeatherForecast[]> GetForecastAsync()
    {
        var token = tokenProvider.AccessToken;
        using var request = new HttpRequestMessage(HttpMethod.Get, 
            "https://localhost:5003/WeatherForecast");
        request.Headers.Add("Authorization", $"Bearer {token}");
        using var response = await http.SendAsync(request);
        response.EnsureSuccessStatusCode();

        return await response.Content.ReadFromJsonAsync<WeatherForecast[]>() ?? 
            Array.Empty<WeatherForecast>();
    }
}

XSRF belirteci bir bileşene geçtiğinde, TokenProvider ekleyin ve XSRF belirtecini POST isteğine dahil edin. Aşağıdaki örnek, belirtecin bir çıkış yapma uç noktası POST isteğine nasıl eklendiğini gösterir. Aşağıdaki örnekteki senaryoda, oturumu kapatma uç noktası (Areas/Identity/Pages/Account/Logout.cshtml, uygulamaya entegre edilmiş olarak ), korunması gereken normal kapatma işlemine ek olarak bazı işlemler gerçekleştirdiği için bir IgnoreAntiforgeryTokenAttribute (@attribute [IgnoreAntiforgeryToken]) belirtmez. Uç nokta, isteği başarıyla işlemek için geçerli bir XSRF belirteci gerektirir.

Yetkili kullanıcılara Oturumu Kapat düğmesi sunan bir bileşende:

@inject TokenProvider TokenProvider

...

<AuthorizeView>
    <Authorized>
        <form action="/Identity/Account/Logout?returnUrl=%2F" method="post">
            <button class="nav-link btn btn-link" type="submit">Logout</button>
            <input name="__RequestVerificationToken" type="hidden" 
                value="@TokenProvider.XsrfToken">
        </form>
    </Authorized>
    <NotAuthorized>
        ...
    </NotAuthorized>
</AuthorizeView>

Kimlik doğrulama düzenini ayarlama

Birden fazla Kimlik Doğrulama Ara Yazılımı kullanan ve dolayısıyla birden fazla kimlik doğrulama şemasına sahip olan bir uygulama için, Blazor tarafından kullanılan düzen, Program dosyasının uç nokta yapılandırmasında açıkça ayarlanabilir. Aşağıdaki örnek OpenID Connect (OIDC) düzenini ayarlar:

Birden fazla Kimlik Doğrulama Ara Yazılımı kullanan ve bu nedenle birden fazla kimlik doğrulama şemasına sahip olan bir uygulama için, Blazor tarafından kullanılan düzen, Startup.cs uç nokta yapılandırmasında açıkça ayarlanabilir. Aşağıdaki örnek OpenID Connect (OIDC) düzenini ayarlar:

using Microsoft.AspNetCore.Authentication.OpenIdConnect;

...

app.MapRazorComponents<App>().RequireAuthorization(
    new AuthorizeAttribute
    {
        AuthenticationSchemes = OpenIdConnectDefaults.AuthenticationScheme
    })
    .AddInteractiveServerRenderMode();
using Microsoft.AspNetCore.Authentication.OpenIdConnect;

...

app.MapBlazorHub().RequireAuthorization(
    new AuthorizeAttribute 
    {
        AuthenticationSchemes = OpenIdConnectDefaults.AuthenticationScheme
    });

Birden fazla Kimlik Doğrulama Ara Yazılımı kullanan ve bu nedenle birden fazla kimlik doğrulama şemasına sahip olan bir uygulama için, Blazor tarafından kullanılan düzen, Startup.Configure uç nokta yapılandırmasında açıkça ayarlanabilir. Aşağıdaki örnek, Microsoft Entra ID düzenini ayarlar:

endpoints.MapBlazorHub().RequireAuthorization(
    new AuthorizeAttribute 
    {
        AuthenticationSchemes = AzureADDefaults.AuthenticationScheme
    });

OpenID Connect (OIDC) v2.0 uç noktalarını kullanma

.NET 5 öncesi ASP.NET Core sürümlerinde, kimlik doğrulama kitaplığı ve Blazor şablonlar OpenID Connect (OIDC) v1.0 uç noktalarını kullanır. ASP.NET Core'un .NET 5 öncesindeki sürümleriyle bir v2.0 uç noktası kullanmak için OpenIdConnectOptions.Authority ayarındaki OpenIdConnectOptions seçeneğini yapılandırın.

services.Configure<OpenIdConnectOptions>(AzureADDefaults.OpenIdScheme, 
    options =>
    {
        options.Authority += "/v2.0";
    }

Alternatif olarak, ayar uygulama ayarları (appsettings.json) dosyasında yapılabilir:

{
  "AzureAd": {
    "Authority": "https://login.microsoftonline.com/common/oauth2/v2.0/",
    ...
  }
}

Yetkiliye bir segment eklemek, uygulamanın OIDC sağlayıcısı için uygun değilse (ME-ID olmayan sağlayıcılar gibi) Authority özelliği doğrudan ayarlayın. Özelliği ya OpenIdConnectOptions içinde ya da Authority anahtarını kullanarak uygulama ayarları dosyasında ayarlayın.

Kod değişiklikleri

  • 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 ID belirtecindeki talepler hakkında yönergeler kimlik belirteci talep referansında ID token claims reference bulunabilir.

  • v2.0 uç noktaları için kapsam URI'lerinde kaynaklar belirtildiğinden, içindeki OpenIdConnectOptions.Resource özelliği ayarını kaldırın OpenIdConnectOptions:

    services.Configure<OpenIdConnectOptions>(AzureADDefaults.OpenIdScheme, options => 
        {
            ...
            options.Resource = "...";    // REMOVE THIS LINE
            ...
        }
    

Uygulama Kimliği URI'si

  • v2.0 uç noktalarını kullanırken, API'ler API için benzersiz bir tanımlayıcıyı temsil eden bir App ID URItanımlar.
  • Tüm kapsamlar ön ek olarak Uygulama Kimliği URI'sini içerir ve v2.0 uç noktaları hedef kitle olarak Uygulama Kimliği URI'si ile erişim belirteçleri yayar.
  • V2.0 uç noktalarını kullanırken, Sunucu API'sinde yapılandırılan istemci kimliği API Uygulama Kimliği'nden (İstemci Kimliği) Uygulama Kimliği URI'sine dönüşür.

appsettings.json:

{
  "AzureAd": {
    ...
    "ClientId": "https://{TENANT}.onmicrosoft.com/{PROJECT NAME}"
    ...
  }
}

Kullanılacak Uygulama Kimliği URI'sini OIDC sağlayıcısı uygulama kayıt açıklamasında bulabilirsiniz.

Özel hizmetler için kullanıcıları kaydetmek amacıyla devre yöneticisi

CircuitHandler'dan bir kullanıcı yakalamak ve kullanıcıyı bir hizmette atamak için AuthenticationStateProvider kullanın. Kullanıcıyı güncelleştirmek istiyorsanız, yeni kullanıcıyı almak ve hizmeti güncelleştirmek için AuthenticationStateChanged öğesine Task bir geri çağırma kaydedin ve bunu sıraya alın. Aşağıdaki örnekte yaklaşımı gösterilmektedir.

Aşağıdaki örnekte:

  • OnConnectionUpAsync , bağlantı hattı her yeniden bağlandığında çağrılır ve kullanıcı bağlantının ömrü boyunca ayarlanır. Yalnızca OnConnectionUpAsync yöntemi gereklidir, tabi ki kimlik doğrulama değişiklikleri için bir işleyici aracılığıyla güncelleştirmeleri uygulamıyorsanız (aşağıdaki örnekte AuthenticationChanged).
  • OnCircuitOpenedAsync , kullanıcıyı güncelleştirmek için kimlik doğrulaması değiştirilmiş işleyicisini AuthenticationChangedeklemek için çağrılır.
  • Kod catch yürütmede UpdateAuthentication bu noktada özel durumları bildirmenin bir yolu olmadığından, görev bloğu özel durumlar üzerinde hiçbir işlem gerçekleştirmez. Görevden bir özel durum oluşturulursa, özel durum uygulamanın başka bir bölümünde bildirilir.

UserService.cs:

using System.Security.Claims;
using Microsoft.AspNetCore.Components.Authorization;
using Microsoft.AspNetCore.Components.Server.Circuits;

public class UserService
{
    private ClaimsPrincipal currentUser = new(new ClaimsIdentity());

    public ClaimsPrincipal GetUser() => currentUser;

    internal void SetUser(ClaimsPrincipal user)
    {
        if (currentUser != user)
        {
            currentUser = user;
        }
    }
}

internal sealed class UserCircuitHandler(
        AuthenticationStateProvider authenticationStateProvider,
        UserService userService) 
        : CircuitHandler, IDisposable
{
    public override Task OnCircuitOpenedAsync(Circuit circuit, 
        CancellationToken cancellationToken)
    {
        authenticationStateProvider.AuthenticationStateChanged += 
            AuthenticationChanged;

        return base.OnCircuitOpenedAsync(circuit, cancellationToken);
    }

    private void AuthenticationChanged(Task<AuthenticationState> task)
    {
        _ = UpdateAuthentication(task);

        async Task UpdateAuthentication(Task<AuthenticationState> task)
        {
            try
            {
                var state = await task;
                userService.SetUser(state.User);
            }
            catch
            {
            }
        }
    }

    public override async Task OnConnectionUpAsync(Circuit circuit, 
        CancellationToken cancellationToken)
    {
        var state = await authenticationStateProvider.GetAuthenticationStateAsync();
        userService.SetUser(state.User);
    }

    public void Dispose()
    {
        authenticationStateProvider.AuthenticationStateChanged -= 
            AuthenticationChanged;
    }
}
using System.Security.Claims;
using Microsoft.AspNetCore.Components.Authorization;
using Microsoft.AspNetCore.Components.Server.Circuits;

public class UserService
{
    private ClaimsPrincipal currentUser = new ClaimsPrincipal(new ClaimsIdentity());

    public ClaimsPrincipal GetUser()
    {
        return currentUser;
    }

    internal void SetUser(ClaimsPrincipal user)
    {
        if (currentUser != user)
        {
            currentUser = user;
        }
    }
}

internal sealed class UserCircuitHandler : CircuitHandler, IDisposable
{
    private readonly AuthenticationStateProvider authenticationStateProvider;
    private readonly UserService userService;

    public UserCircuitHandler(
        AuthenticationStateProvider authenticationStateProvider,
        UserService userService)
    {
        this.authenticationStateProvider = authenticationStateProvider;
        this.userService = userService;
    }

    public override Task OnCircuitOpenedAsync(Circuit circuit, 
        CancellationToken cancellationToken)
    {
        authenticationStateProvider.AuthenticationStateChanged += 
            AuthenticationChanged;

        return base.OnCircuitOpenedAsync(circuit, cancellationToken);
    }

    private void AuthenticationChanged(Task<AuthenticationState> task)
    {
        _ = UpdateAuthentication(task);

        async Task UpdateAuthentication(Task<AuthenticationState> task)
        {
            try
            {
                var state = await task;
                userService.SetUser(state.User);
            }
            catch
            {
            }
        }
    }

    public override async Task OnConnectionUpAsync(Circuit circuit, 
        CancellationToken cancellationToken)
    {
        var state = await authenticationStateProvider.GetAuthenticationStateAsync();
        userService.SetUser(state.User);
    }

    public void Dispose()
    {
        authenticationStateProvider.AuthenticationStateChanged -= 
            AuthenticationChanged;
    }
}

Program dosyasında:

using Microsoft.AspNetCore.Components.Server.Circuits;
using Microsoft.Extensions.DependencyInjection.Extensions;

...

builder.Services.AddScoped<UserService>();
builder.Services.TryAddEnumerable(
    ServiceDescriptor.Scoped<CircuitHandler, UserCircuitHandler>());

Startup.ConfigureServicesiçindeStartup.cs:

using Microsoft.AspNetCore.Components.Server.Circuits;
using Microsoft.Extensions.DependencyInjection.Extensions;

...

services.AddScoped<UserService>();
services.TryAddEnumerable(
    ServiceDescriptor.Scoped<CircuitHandler, UserCircuitHandler>());

Kullanıcıyı edinmek için bir bileşendeki hizmeti kullanın:

@inject UserService UserService

<h1>Hello, @(UserService.GetUser().Identity?.Name ?? "world")!</h1>

Kullanıcıyı MVC, Razor Sayfalar ve diğer ASP.NET Core senaryolarında ara yazılımda ayarlamak için, Kimlik Doğrulama Ara Yazılımı çalıştırıldıktan sonra özel ara yazılımda SetUserUserService öğesini çağırın veya kullanıcıyı bir IClaimsTransformation uygulamayla ayarlayın. Aşağıdaki örnek ara yazılım yaklaşımını benimser.

UserServiceMiddleware.cs:

public class UserServiceMiddleware
{
    private readonly RequestDelegate next;

    public UserServiceMiddleware(RequestDelegate next)
    {
        this.next = next ?? throw new ArgumentNullException(nameof(next));
    }

    public async Task InvokeAsync(HttpContext context, UserService service)
    {
        service.SetUser(context.User);
        await next(context);
    }
}

dosyasındaki çağrısından hemen önce ara yazılımı çağırın:

dosyasındaki çağrısından hemen önce ara yazılımı çağırın:

app.MapBlazorHub() içindeki Startup.Configure'deki Startup.cs çağrısından hemen önce ara yazılımı çağırın.

app.UseMiddleware<UserServiceMiddleware>();

Çıkış yapan istek ara yazılımında AuthenticationStateProvider'ye erişim

AuthenticationStateProvider ile DelegatingHandler oluşturulan için HttpClientIHttpClientFactory öğesine giden istek ara yazılımında bağlantı hattı etkinlik işleyicisi kullanılarak erişilebilir.

Not

ASP.NET Core uygulamalarında kullanılarak HttpClient oluşturulan örneklere göre IHttpClientFactory HTTP istekleri için temsilci işleyicileri tanımlama hakkında genel yönergeler için, ASP.NET Core'da IHttpClientFactory kullanarak HTTP istekleri oluşturma'nın aşağıdaki bölümlerine bakın:

Aşağıdaki örnek, giden isteklere kimliği doğrulanmış kullanıcılar için özel bir kullanıcı adı üst bilgisi eklemek için kullanır AuthenticationStateProvider .

İlk olarak, CircuitServicesAccessor sınıfını, Blazor bağımlılık ekleme (DI) makalesinin aşağıdaki bölümünde uygulayın.

Farklı bir DI kapsamından sunucu tarafı Blazor hizmetlerine erişme

CircuitServicesAccessor öğesini AuthenticationStateProvider uygulamasında DelegatingHandler öğesine erişmek için kullanın.

AuthenticationStateHandler.cs:

using Microsoft.AspNetCore.Components.Authorization;

public class AuthenticationStateHandler(
    CircuitServicesAccessor circuitServicesAccessor) 
    : DelegatingHandler
{
    protected override async Task<HttpResponseMessage> SendAsync(
        HttpRequestMessage request, CancellationToken cancellationToken)
    {
        var authStateProvider = circuitServicesAccessor.Services?
            .GetRequiredService<AuthenticationStateProvider>();

        if (authStateProvider is null)
        {
            throw new Exception("AuthenticationStateProvider not available");
        }

        var authState = await authStateProvider.GetAuthenticationStateAsync();

        var user = authState?.User;

        if (user?.Identity is not null && user.Identity.IsAuthenticated)
        {
            request.Headers.Add("X-USER-IDENTITY-NAME", user.Identity.Name);
        }

        return await base.SendAsync(request, cancellationToken);
    }
}

Program dosyasında AuthenticationStateHandler kaydedin ve IHttpClientFactory öğesine, HttpClient örneklerini oluşturan işleyiciyi ekleyin.

builder.Services.AddTransient<AuthenticationStateHandler>();

builder.Services.AddHttpClient("HttpMessageHandler")
    .AddHttpMessageHandler<AuthenticationStateHandler>();