Megosztás a következőn keresztül:


ASP.NET Core további Blazor WebAssembly biztonsági forgatókönyvek

Note

Ez nem a cikk legújabb verziója. Az aktuális kiadásról a cikk .NET 10-es verziójában olvashat.

Warning

A ASP.NET Core ezen verziója már nem támogatott. További információ: .NET és .NET Core támogatási szabályzat. A jelen cikk .NET 9-es verzióját lásd az aktuális kiadásért .

Ez a cikk az alkalmazások további biztonsági forgatókönyveit Blazor WebAssembly ismerteti.

Tokenek csatolása kimenő kérelmekhez

AuthorizationMessageHandler egy DelegatingHandler, amelyet a hozzáférési jogkivonatok feldolgozására használnak. A jogkivonatok a IAccessTokenProvider keretrendszer által regisztrált szolgáltatás használatával lesznek beolvasva. Ha egy jogkivonat nem szerezhető be, a rendszer egy AccessTokenNotAvailableException kivételt dob. AccessTokenNotAvailableException rendelkezik egy Redirect metódussal, amely a megadott AccessTokenResult.InteractiveRequestUrl használatával navigál a AccessTokenResult.InteractionOptions felé, lehetővé téve a hozzáférési token frissítését.

A kényelem érdekében a keretrendszer előre konfigurálja az BaseAddressAuthorizationMessageHandler alkalmazás alapcímét engedélyezett URL-címként. A hozzáférési jogkivonatok csak akkor lesznek hozzáadva, ha a kérelem URI-ja az alkalmazás alapszintű URI-ján belül van. Ha a kimenő kérelmek URI-i nem tartoznak az alkalmazás alapszintű URI-ja közé, használjon egyéni AuthorizationMessageHandler osztályt (ajánlott), vagy konfigurálja a AuthorizationMessageHandler.

Note

A kiszolgálói API-hozzáférés ügyfélalkalmazás-konfigurációján kívül a kiszolgálói API-nak engedélyeznie kell a forrásközi kérelmeket (CORS), ha az ügyfél és a kiszolgáló nem ugyanazon az alapcímen található. A kiszolgálóoldali CORS-konfigurációval kapcsolatos további információkért tekintse meg a cikk későbbi, forrásközi erőforrás-megosztási (CORS) szakaszát.

Az alábbi példában:

Az alábbi példában a HttpClientFactoryServiceCollectionExtensions.AddHttpClient egy bővítmény a Microsoft.Extensions.Http-ben. Adja hozzá a csomagot egy olyan alkalmazáshoz, amely még nem hivatkozik rá.

Note

A csomagok .NET-alkalmazásokhoz való hozzáadásáról a Csomagok telepítése és kezeléseCsomaghasználati munkafolyamat (NuGet-dokumentáció)című cikkben talál útmutatást. Ellenőrizze a megfelelő csomagverziókat a 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"));

ABlazor projektsablonon alapuló üzemeltetett megoldások esetében a Blazor WebAssemblykérelem URI-k az alkalmazás alapszintű URI-ján belül találhatók. IWebAssemblyHostEnvironment.BaseAddress Ezért (new Uri(builder.HostEnvironment.BaseAddress)) hozzá van rendelve a HttpClient.BaseAddress projektsablonból létrehozott alkalmazáshoz.

A konfigurált HttpClient használatával megbízható kérések történnek a try-catch mintával:

@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();
    }
}

Egyéni hitelesítési kérelmek forgatókönyvei

Az alábbi forgatókönyvek bemutatják, hogyan szabhatja testre a hitelesítési kérelmeket, és hogyan szerezheti be a bejelentkezési útvonalat a hitelesítési beállításokból.

A bejelentkezési folyamat testreszabása

A bejelentkezési kérelmek további paramétereinek kezelése az alábbi módszerekkel egy vagy több alkalommal a következő új példányon InteractiveRequestOptions:

Az alábbi LoginDisplay összetevő-példában további paramétereket adunk hozzá a bejelentkezési kérelemhez:

  • prompt a következőre loginvan állítva: Kényszeríti a felhasználót, hogy adja meg a hitelesítő adatait a kéréshez, és ne kapcsolja be az egyszeri bejelentkezést.
  • loginHint beállítása peter@contoso.com: Előre kitölti a bejelentkezési oldal felhasználónév/e-mail-cím mezőjét a felhasználónak peter@contoso.com. Az alkalmazások gyakran használják ezt a paramétert az újrahitelesítés során, miután már kinyerték a felhasználónevet egy korábbi bejelentkezésből a preferred_username jogcím használatával.

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);
    }
}

További információt a következő források tartalmaznak:

Az opciók testreszabása, mielőtt a tokent interaktívan megszerezné

Ha AccessTokenNotAvailableException bekövetkezik, az új identitásszolgáltató hozzáférési token kéréséhez szükséges további paramétereket a következő módszerekkel kezelje egy vagy több alkalommal egy új InteractiveRequestOptions példányon:

A következő példában, amely jSON-adatokat szerez be a webes API-n keresztül, további paramétereket ad hozzá az átirányítási kérelemhez, ha egy hozzáférési jogkivonat nem érhető el (AccessTokenNotAvailableException a rendszer eldobja):

  • prompt a következőre loginvan állítva: Kényszeríti a felhasználót, hogy adja meg a hitelesítő adatait a kéréshez, és ne kapcsolja be az egyszeri bejelentkezést.
  • loginHint beállítása peter@contoso.com: Előre kitölti a bejelentkezési oldal felhasználónév/e-mail-cím mezőjét a felhasználónak peter@contoso.com. Az alkalmazások gyakran használják ezt a paramétert az újrahitelesítés során, miután már kinyerték a felhasználónevet egy korábbi bejelentkezésből a preferred_username jogcím használatával.
try
{
    var examples = await Http.GetFromJsonAsync<ExampleType[]>("ExampleAPIMethod");

    ...
}
catch (AccessTokenNotAvailableException ex)
{
    ex.Redirect(requestOptions => {
        requestOptions.TryAddAdditionalParameter("prompt", "login");
        requestOptions.TryAddAdditionalParameter("loginHint", "peter@contoso.com");
    });
}

Az előző példa a következőket feltételezi:

További információt a következő források tartalmaznak:

Beállítások testreszabása IAccessTokenProvider használatakor

Ha a jogkivonat beszerzése sikertelen egy IAccessTokenProviderúj példány használatakor, kezelje az új identitásszolgáltató hozzáférési jogkivonat-kérésének további paramétereit a következő módszerekkel egy vagy több alkalommal egy új példányon InteractiveRequestOptions:

A következő példában, amely megpróbál hozzáférési jogkivonatot szerezni a felhasználó számára, további paramétereket ad hozzá a bejelentkezési kérelemhez, ha a jogkivonat beszerzésére tett kísérlet sikertelen, amikor TryGetToken meghívják:

  • prompt a következőre loginvan állítva: Kényszeríti a felhasználót, hogy adja meg a hitelesítő adatait a kéréshez, és ne kapcsolja be az egyszeri bejelentkezést.
  • loginHint beállítása peter@contoso.com: Előre kitölti a bejelentkezési oldal felhasználónév/e-mail-cím mezőjét a felhasználónak peter@contoso.com. Az alkalmazások gyakran használják ezt a paramétert az újrahitelesítés során, miután már kinyerték a felhasználónevet egy korábbi bejelentkezésből a preferred_username jogcím használatával.
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);
}

Az előző példa a következőket feltételezi:

További információt a következő források tartalmaznak:

Kijelentkezés egyéni visszatérési URL-címmel

Az alábbi példa kijelentkezteti a felhasználót, és visszaadja a felhasználót a /goodbye végpontnak:

Navigation.NavigateToLogout("authentication/logout", "goodbye");

A bejelentkezési útvonal lekérése a hitelesítési beállításokból

Szerezze be a konfigurált bejelentkezési útvonalat a következő forrásból RemoteAuthenticationOptions:

var loginPath = 
    RemoteAuthOptions.Get(Options.DefaultName).AuthenticationPaths.LogInPath;

Az előző példa a következőket feltételezi:

Egyéni AuthorizationMessageHandler osztály

Ez az útmutató azoknak az ügyfélalkalmazásoknak ajánlott, amelyek kimenő kéréseket intéznek olyan URI-khoz, amelyek nem az alkalmazás alapszintű URI-ján belül találhatók.

Az alábbi példában egy egyéni osztály kiterjeszti a AuthorizationMessageHandler-t, hogy DelegatingHandler-ként használható legyen egy HttpClient számára. ConfigureHandler ezt a kezelőt úgy konfigurálja, hogy hozzáférési jogkivonat használatával engedélyezze a kimenő HTTP-kéréseket. A hozzáférési jogkivonat csak akkor van csatolva, ha az engedélyezett URL-címek közül legalább az egyik a kérelem URI (HttpRequestMessage.RequestUri) alapja.

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

Ebben a szakaszban a rendszer az előző üzenetkezelőt használja, amikor egy konfigurált HttpClient fájl egy beszúrt IHttpClientFactoryfájlból jön létre. Ha nem használ egy IHttpClientFactory, létre kell hoznia egy HttpClientHandler példányt, és hozzá kell rendelnie a AuthorizationMessageHandlerDelegatingHandler.InnerHandler-hez.

InnerHandler = new HttpClientHandler();

Ha a InnerHandler-et használja, nem kell elvégeznie az előző IHttpClientFactory hozzárendelést, ahogy azt a ExampleAPIMethod hívás ebben a szakaszban mutatja.

Az előző kódban a hatókörök example.read és example.write általános példák, nem egy adott szolgáltató érvényes hatóköreinek példái.

A Program fájlban a CustomAuthorizationMessageHandler átmeneti szolgáltatásként van regisztrálva, és úgy van beállítva, mint a kimenő DelegatingHandler példányok HttpResponseMessage, amelyeket egy megnevezett HttpClient hoz létre.

Az alábbi példában a HttpClientFactoryServiceCollectionExtensions.AddHttpClient egy bővítmény a Microsoft.Extensions.Http-ben. Adja hozzá a csomagot egy olyan alkalmazáshoz, amely még nem hivatkozik rá.

Note

A csomagok .NET-alkalmazásokhoz való hozzáadásáról a Csomagok telepítése és kezeléseCsomaghasználati munkafolyamat (NuGet-dokumentáció)című cikkben talál útmutatást. Ellenőrizze a megfelelő csomagverziókat a NuGet.org.

builder.Services.AddTransient<CustomAuthorizationMessageHandler>();

builder.Services.AddHttpClient("WebAPI",
        client => client.BaseAddress = new Uri("https://api.contoso.com/v1.0"))
    .AddHttpMessageHandler<CustomAuthorizationMessageHandler>();

Note

Az előző példában a CustomAuthorizationMessageHandlerDelegatingHandler rendszer átmeneti szolgáltatásként van regisztrálva a következőhöz AddHttpMessageHandler: . Az átmeneti regisztráció ajánlott a IHttpClientFactory számára, amely a saját DI-hatóköröket kezeli. További információt a következő források tartalmaznak:

Egy Blazor alapú üzemeltetett Blazor WebAssembly megoldás esetén (IWebAssemblyHostEnvironment.BaseAddress) a new Uri(builder.HostEnvironment.BaseAddress)-höz van hozzárendelve.

A konfigurált HttpClient arra szolgál, hogy a try-catch mintával hitelesített kéréseket tegyen. Ahol a kliens a CreateClient (Microsoft.Extensions.Http csomag) segítségével van létrehozva, a HttpClient példányai hozzáférési tokeneket tartalmaznak a kiszolgáló API-ra irányuló kérések során. Ha a kérelem URI-ja relatív URI, ahogyan az a következő példában is szerepel (ExampleAPIMethod), az össze van kombinálva a BaseAddress-val, amikor az ügyfélalkalmazás kérést küld.

@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();
        }
    }
}

AuthorizationMessageHandler konfigurálása

A AuthorizationMessageHandler a ConfigureHandler metódussal konfigurálható engedélyezett URL-címek, hatókörök és egy visszatérési URL-cím használatával. ConfigureHandler a kezelőt úgy konfigurálja, hogy hozzáférési jogkivonat használatával engedélyezze a kimenő HTTP-kéréseket. A hozzáférési jogkivonat csak akkor van csatolva, ha az engedélyezett URL-címek közül legalább az egyik a kérelem URI (HttpRequestMessage.RequestUri) alapja. Ha a kérelem URI-ja relatív URI, akkor össze van kombinálva a BaseAddress-val.

A következő példában a AuthorizationMessageHandler konfigurál egy HttpClient-t a Program fájlban.

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")
});

Az előző kódban:

A Blazor projektsablonon alapuló üzemeltetett Blazor WebAssembly megoldás esetében a a következőkhöz van hozzárendelve:

Gépelt HttpClient

Definiálható egy típusos kliens, amely egyetlen osztályon belül kezeli az összes HTTP- és token-beszerzési feladatot.

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>();
    }
}

Az előző példában a WeatherForecast típus egy statikus osztály, amely időjárás-előrejelzési adatokat tárol. A {PACKAGE ID/ASSEMBLY NAME} helyőrző a projekt csomagazonosítója (<PackageId> a projektfájlban) egy alkalmazás kódtárának vagy szerelvénynevének (például using static BlazorSample.Data;).

Az alábbi példában a HttpClientFactoryServiceCollectionExtensions.AddHttpClient egy bővítmény a Microsoft.Extensions.Http-ben. Adja hozzá a csomagot egy olyan alkalmazáshoz, amely még nem hivatkozik rá.

Note

A csomagok .NET-alkalmazásokhoz való hozzáadásáról a Csomagok telepítése és kezeléseCsomaghasználati munkafolyamat (NuGet-dokumentáció)című cikkben talál útmutatást. Ellenőrizze a megfelelő csomagverziókat a NuGet.org.

A Program fájlban:

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>();

Egy Blazor alapú üzemeltetett Blazor WebAssembly megoldás esetén (IWebAssemblyHostEnvironment.BaseAddress) a new Uri(builder.HostEnvironment.BaseAddress)-höz van hozzárendelve.

Időjárási adatokat beolvasó összetevőben:

@inject WeatherForecastClient Client

...

protected override async Task OnInitializedAsync()
{
    forecasts = await Client.GetForecastAsync();
}

A HttpClient kezelő konfigurálása

Tovább lehet konfigurálni a kezelőt kimenő HTTP-kérésekhez a ConfigureHandler segítségével.

Az alábbi példában a HttpClientFactoryServiceCollectionExtensions.AddHttpClient egy bővítmény a Microsoft.Extensions.Http-ben. Adja hozzá a csomagot egy olyan alkalmazáshoz, amely még nem hivatkozik rá.

Note

A csomagok .NET-alkalmazásokhoz való hozzáadásáról a Csomagok telepítése és kezeléseCsomaghasználati munkafolyamat (NuGet-dokumentáció)című cikkben talál útmutatást. Ellenőrizze a megfelelő csomagverziókat a NuGet.org.

A Program fájlban:

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" }));

Az előző kódban a hatókörök example.read és example.write általános példák, nem egy adott szolgáltató érvényes hatóköreinek példái.

A Blazor projektsablonon alapuló üzemeltetett Blazor WebAssembly megoldás esetében a a következőkhöz van hozzárendelve:

Nem hitelesített vagy jogosulatlan webes API-kérések egy biztonságos alapértelmezett ügyféllel rendelkező alkalmazásban

Az általában biztonságos alapértelmezettet HttpClient használó alkalmazások egy névvel ellátott HttpClientbeállítás konfigurálásával hitelesítés nélküli vagy jogosulatlan webes API-kéréseket is kezdeményezhetnek.

Az alábbi példában a HttpClientFactoryServiceCollectionExtensions.AddHttpClient egy bővítmény a Microsoft.Extensions.Http-ben. Adja hozzá a csomagot egy olyan alkalmazáshoz, amely még nem hivatkozik rá.

Note

A csomagok .NET-alkalmazásokhoz való hozzáadásáról a Csomagok telepítése és kezeléseCsomaghasználati munkafolyamat (NuGet-dokumentáció)című cikkben talál útmutatást. Ellenőrizze a megfelelő csomagverziókat a NuGet.org.

A Program fájlban:

builder.Services.AddHttpClient("WebAPI.NoAuthenticationClient", 
    client => client.BaseAddress = new Uri("https://api.contoso.com/v1.0"));

Egy Blazor alapú üzemeltetett Blazor WebAssembly megoldás esetén (IWebAssemblyHostEnvironment.BaseAddress) a new Uri(builder.HostEnvironment.BaseAddress)-höz van hozzárendelve.

Az előbbi regisztráció a meglévő biztonságos alapértelmezett HttpClient regisztráció mellett történik meg.

Egy összetevő létrehozza a HttpClient a IHttpClientFactory (Microsoft.Extensions.Http csomag) felhasználásával, hogy hitelesítés nélküli vagy jogosulatlan kéréseket tegyen.

@inject IHttpClientFactory ClientFactory

...

@code {
    protected override async Task OnInitializedAsync()
    {
        var client = ClientFactory.CreateClient("WebAPI.NoAuthenticationClient");

        var examples = await client.GetFromJsonAsync<ExampleType[]>(
            "ExampleNoAuthentication");

        ...
    }
}

Note

A kiszolgálói API ExampleNoAuthenticationController vezérlője az előző példában nincs megjelölve az [Authorize] attribútummal.

A fejlesztő dönti el, hogy biztonságos vagy nem biztonságos ügyfelet használ-e alapértelmezett HttpClient példányként. Ennek a döntésnek az egyik módja, ha figyelembe veszi a hitelesített és a hitelesítés nélküli végpontok számát, amelyekkel az alkalmazás kapcsolatba lép. Ha az alkalmazás kéréseinek többsége az API-végpontok védelmére irányul, használja alapértelmezettként a hitelesített HttpClient példányt. Ellenkező esetben a hitelesítés nélküli HttpClient példányt regisztrálja alapértelmezettként.

A IHttpClientFactory használatának alternatív megközelítése, ha egy típusos klienst hozunk létre névtelen végpontokhoz való hitelesítés nélkül történő hozzáféréshez.

További hozzáférési jogkivonatok kérése

A hozzáférési jogkivonatok manuálisan is beszerezhetők a hívással IAccessTokenProvider.RequestAccessToken. Az alábbi példában egy alkalmazás további hatókört igényel az alapértelmezett HttpClientbeállításhoz. A Microsoft Authentication Library (MSAL) példa a következővel konfigurálja a hatókört MsalProviderOptions:

A Program fájlban:

builder.Services.AddMsalAuthentication(options =>
{
    ...

    options.ProviderOptions.AdditionalScopesToConsent.Add("{CUSTOM SCOPE 1}");
    options.ProviderOptions.AdditionalScopesToConsent.Add("{CUSTOM SCOPE 2}");
}

Az előző példában szereplő {CUSTOM SCOPE 1} és {CUSTOM SCOPE 2} helyőrzők testreszabott hatókörök.

Note

AdditionalScopesToConsent nem tud delegált felhasználói engedélyeket kiépíteni a Microsoft Graph számára a Microsoft Entra ID hozzájárulási felhasználói felületén keresztül, amikor egy felhasználó először használ egy Microsoft Azure-ban regisztrált alkalmazást. További információért lásd: A Graph API használata ASP.NET Core-tal Blazor WebAssembly.

A IAccessTokenProvider.RequestAccessToken metódus túlterhelést biztosít, amely lehetővé teszi, hogy egy alkalmazás hozzáférési jogkivonatot építsen ki egy adott hatókörökkel.

Egy Razor összetevőben:

@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))
{
    ...
}

Az előző példában szereplő {CUSTOM SCOPE 1} és {CUSTOM SCOPE 2} helyőrzők testreszabott hatókörök.

AccessTokenResult.TryGetToken a következőt adja vissza:

  • true a token használatra.
  • false ha a jogkivonat nincs lekérve.

Forrásközi erőforrás-megosztás (CORS)

Hitelesítő adatok (hitelesítési cookie-k/fejlécek) CORS-kérelmeken való küldésekor a Authorization fejlécet engedélyeznie kell a CORS-szabályzatnak.

A következő szabályzat a következő konfigurációt tartalmazza:

  • A kérések eredete (http://localhost:5000, https://localhost:5001).
  • Bármely módszer (ige).
  • Content-Type és Authorization fejlécek. Annak engedélyezéséhez, hogy egyéni fejlécet használjon (például x-custom-header), sorolja fel a fejlécet, amikor a WithHeaders-t hívja.
  • Ügyféloldali JavaScript-kód által beállított hitelesítő adatok (credentials a tulajdonság értéke: include).
app.UseCors(policy => 
    policy.WithOrigins("http://localhost:5000", "https://localhost:5001")
        .AllowAnyMethod()
        .WithHeaders(HeaderNames.ContentType, HeaderNames.Authorization, 
            "x-custom-header")
        .AllowCredentials());

A Blazor üzemeltetett Blazor WebAssembly megoldások ugyanazt az alapcímet használják az ügyfél- és kiszolgálóalkalmazásokhoz. Az ügyfélalkalmazás HttpClient.BaseAddress a builder.HostEnvironment.BaseAddress URI-re van állítva. A CORS-konfiguráció nem szükséges egy üzemeltetett Blazor megoldás alapértelmezett konfigurációjában. A kiszolgálóprojekt által nem üzemeltetett és a kiszolgálóalkalmazás alapcímét nem megosztó további ügyfélalkalmazások esetében cors-konfigurációra van szükség a kiszolgálóprojektben.

További információ: A kereszt-eredetű kérelmek engedélyezése (CORS) a ASP.NET Core-ban és a mintaalkalmazás HTTP-kérelemtesztelő összetevőjében (Components/HTTPRequestTester.razor).

Tokenkérések hibáinak kezelése

Ha egy egyoldalas alkalmazás (SPA) az OpenID Connect (OIDC) használatával hitelesít egy felhasználót, a hitelesítési állapot helyileg marad fenn az SPA-ban és a Identity szolgáltatóban (IP-ben) egy olyan munkamenet cookie formájában, amelyet a felhasználó a hitelesítő adataik megadásával állít be.

Az IP-cím által a felhasználó számára kibocsátott jogkivonatok általában rövid ideig, általában egy óráig érvényesek, ezért az ügyfélalkalmazásnak rendszeresen be kell kérnie az új jogkivonatokat. Ellenkező esetben a rendszer kijelentkezteti a felhasználót a megadott jogkivonatok lejárta után. Az OIDC-ügyfelek a legtöbb esetben anélkül tudnak új jogkivonatokat beszerezni, hogy a felhasználónak újra hitelesítenie kellene magát az IdP-ben tárolt hitelesítési állapotnak vagy "session-nek" köszönhetően.

Vannak olyan esetek, amikor az ügyfél nem tud jogkivonatot lekérni felhasználói beavatkozás nélkül, például amikor a felhasználó valamilyen okból kifejezetten kijelentkezik az IP-címről. Ez a forgatókönyv akkor fordul elő, ha egy felhasználó meglátogatja https://login.microsoftonline.com és kijelentkezik. Ezekben az esetekben az alkalmazás nem tudja azonnal, hogy a felhasználó kijelentkezett. Előfordulhat, hogy az ügyfél által birtokolt tokenek már nem érvényesek. Emellett az ügyfél nem tud új jogkivonatot kiépíteni felhasználói beavatkozás nélkül az aktuális jogkivonat lejárata után.

Ezek a forgatókönyvek nem kizárólag a jogkivonatalapú hitelesítésre vonatkoznak. Ezek a SPÁ-k természetének részét képezik. A cookie-kat használó SPA nem hív meg kiszolgálói API-t is, ha a hitelesítést cookie eltávolítják.

Ha egy alkalmazás API-hívásokat hajt végre védett erőforrásokhoz, tisztában kell lennie a következőkkel:

  • Ha új hozzáférési jogkivonatot szeretne kiépíteni az API meghívásához, előfordulhat, hogy a felhasználónak újra hitelesítenie kell magát.
  • Még ha az ügyfél rendelkezik érvényesnek tűnő jogkivonattal is, előfordulhat, hogy a kiszolgáló hívása meghiúsul, mert a felhasználó visszavonta a jogkivonatot.

Amikor az alkalmazás tokent kér, két lehetséges kimenetel van.

  • A kérés sikeres, és az alkalmazás érvényes jogkivonattal rendelkezik.
  • A kérés sikertelen, és az alkalmazásnak újra hitelesítenie kell a felhasználót egy új jogkivonat beszerzéséhez.

Ha egy jogkivonat-kérés meghiúsul, el kell döntenie, hogy menteni szeretné-e az aktuális állapotot az átirányítás végrehajtása előtt. Az állapot tárolására számos megközelítés létezik, amelyek egyre összetettebbé növelődnek:

  • Tárolja az aktuális oldal állapotát a munkamenet tárolásában. OnInitializedAsync Az életciklus-módszer (OnInitializedAsync) során ellenőrizze, hogy visszaállítható-e az állapot a folytatás előtt.
  • Adjon hozzá egy lekérdezési sztringparamétert, és ezzel jelezheti az alkalmazásnak, hogy újra kell hidratálnia a korábban mentett állapotot.
  • Adjon hozzá egy egyedi azonosítójú lekérdezési sztringparamétert az adatok munkamenet-tárolóban való tárolásához anélkül, hogy más elemekkel való ütközést kockáztathat.

Alkalmazásállapot mentése munkamenet-tárolóval végzett hitelesítési művelet előtt

Az alábbi példa bemutatja, hogyan:

  • A bejelentkezési lapra való átirányítás előtt őrizze meg az állapotot.
  • Az előző állapot helyreállítása lekérdezési sztringparaméter használatával végzett hitelesítés utá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; }
    }
}

Alkalmazásállapot mentése munkamenet-tárolóval és állapottárolóval végzett hitelesítési művelet előtt

A hitelesítési művelet során előfordulhat, hogy a böngésző IP-címére való átirányítása előtt menteni szeretné az alkalmazás állapotát. Ez akkor lehet így, ha állapottárolót használ, és a hitelesítés sikeres végrehajtása után vissza szeretné állítani az állapotot. Egyéni hitelesítési állapotobjektumokkal megőrizheti az alkalmazásspecifikus állapotot, vagy hivatkozhat rá, és visszaállíthatja az állapotot a hitelesítési művelet sikeres befejezése után. Az alábbi példa a megközelítést mutatja be.

Létrejön egy állapottároló-osztály az alkalmazásban az alkalmazás állapotértékeinek tárolásához szükséges tulajdonságokkal. Az alábbi példában a tároló az alapértelmezett Blazor projektsablonCounter összetevőjének (Counter.razor) számlálóértékének fenntartására szolgál. A tároló szerializálásának és deszerializálásának módszerei a következők: 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;
    }
}

Az Counter összetevő az állapottárolót használja az currentCount összetevőn kívüli érték fenntartásához:

@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;
    }
}

Hozzon létre egy ApplicationAuthenticationStateRemoteAuthenticationState-ból. Adjon meg egy tulajdonságot Id , amely a helyileg tárolt állapot azonosítójaként szolgál.

ApplicationAuthenticationState.cs:

using Microsoft.AspNetCore.Components.WebAssembly.Authentication;

public class ApplicationAuthenticationState : RemoteAuthenticationState
{
    public string? Id { get; set; }
}

Az Authentication összetevő (Authentication.razor) a szerializálási és deszerializálási módszerekkel menti és visszaállítja az alkalmazás állapotát a StateContainer helyi munkamenet-tároló használatával, GetStateForLocalStorage és SetStateFromLocalStorage:

@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);
            }
        }
    }
}

Ez a példa a Microsoft Entra rendszerét (ME-ID) használja a hitelesítéshez. A Program fájlban:

  • Ez ApplicationAuthenticationState Microsoft Authentication Library (MSAL) RemoteAuthenticationState típusként van konfigurálva.
  • Az állapottároló regisztrálva van a szolgáltatástárolóban.
builder.Services.AddMsalAuthentication<ApplicationAuthenticationState>(options =>
{
    builder.Configuration.Bind("AzureAd", options.ProviderOptions.Authentication);
});

builder.Services.AddSingleton<StateContainer>();

Alkalmazásútvonalak testreszabása

A Microsoft.AspNetCore.Components.WebAssembly.Authentication kódtár az alábbi táblázatban látható útvonalakat használja a különböző hitelesítési állapotok ábrázolása érdekében.

Route Purpose
authentication/login Bejelentkezési műveletet indít el.
authentication/login-callback Kezeli bármely bejelentkezési művelet eredményét.
authentication/login-failed Hibaüzeneteket jelenít meg, ha a bejelentkezési művelet valamilyen okból meghiúsul.
authentication/logout Kijelentkezési műveletet indít el.
authentication/logout-callback Kezeli a kijelentkezési művelet eredményét.
authentication/logout-failed Hibaüzeneteket jelenít meg, ha a kijelentkezési művelet valamilyen okból meghiúsul.
authentication/logged-out Azt jelzi, hogy a felhasználó sikeresen kijelentkezett.
authentication/profile Elindít egy műveletet a felhasználói profil szerkesztéséhez.
authentication/register Új felhasználó regisztrálásához aktivál egy műveletet.

Az előző táblázatban látható útvonalak konfigurálhatók a következő módon RemoteAuthenticationOptions<TRemoteAuthenticationProviderOptions>.AuthenticationPaths: . Ha egyéni útvonalak megadására vonatkozó beállításokat ad meg, győződjön meg arról, hogy az alkalmazás rendelkezik egy útvonalsal, amely kezeli az egyes útvonalakat.

Az alábbi példában az összes elérési út előtaggal /securityvan elnevezve.

Authentication összetevő (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; }
}

A Program fájlban:

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";
});

Ha a követelmény teljesen eltérő útvonalakat hív meg, állítsa be az útvonalakat a korábban leírt módon, és renderelje azokat RemoteAuthenticatorView explicit műveleti paraméterrel:

@page "/register"

<RemoteAuthenticatorView Action="RemoteAuthenticationActions.Register" />

Ha ezt választja, a felhasználói felületet különböző oldalakra bonthatja.

A hitelesítési felhasználói felület testreszabása

RemoteAuthenticatorView az egyes hitelesítési állapotokhoz tartozó felhasználói felületi töredékek alapértelmezett készletét tartalmazza. Minden állapot testre szabható egyéni RenderFragmentátadással. Ha testre szeretné szabni a megjelenített szöveget a kezdeti bejelentkezési folyamat során, az alábbiak szerint módosíthatja a RemoteAuthenticatorView szöveget.

Authentication összetevő (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 RemoteAuthenticatorView következő táblázatban látható hitelesítési útvonalonként egy töredék használható.

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>

A felhasználó testreszabása

Az alkalmazáshoz kötött felhasználók testre szabhatók.

A felhasználó testreszabása egy payload-igénnyel

A következő példában az alkalmazás hitelesített felhasználói minden saját hitelesítési módszerükhöz kapnak egy amr jogcímet. A amr jogcím azonosítja, hogy a jogkivonat tárgya hogyan lett azonosítva a Microsoft identity platform v1.0 hasznos adat jogcímeiben. A példa egy egyedi felhasználói fiók osztályt használ, amely a(z) RemoteUserAccount alapul.

Hozzon létre egy osztályt, amely kibővíti az osztályt RemoteUserAccount . Az alábbi példa a AuthenticationMethod tulajdonságot a felhasználó amr JSON tulajdonságértékeinek tömbjére állítja be. AuthenticationMethod a keretrendszer automatikusan kitölti a felhasználó hitelesítésekor.

using System.Text.Json.Serialization;
using Microsoft.AspNetCore.Components.WebAssembly.Authentication;

public class CustomUserAccount : RemoteUserAccount
{
    [JsonPropertyName("amr")]
    public string[]? AuthenticationMethod { get; set; }
}

Hozzon létre egy gyárat, amely kiterjeszti AccountClaimsPrincipalFactory<TAccount>-t a CustomUserAccount.AuthenticationMethod-ben tárolt felhasználói hitelesítési módszerek alapján jogcímek létrehozására.

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;
    }
}

Regisztrálja a CustomAccountFactory a jelenleg használt hitelesítésszolgáltatóhoz. Az alábbi regisztrációk bármelyike érvényes:

  • AddOidcAuthentication:

    using Microsoft.AspNetCore.Components.WebAssembly.Authentication;
    
    ...
    
    builder.Services.AddOidcAuthentication<RemoteAuthenticationState, 
        CustomUserAccount>(options =>
        {
            ...
        })
        .AddAccountClaimsPrincipalFactory<RemoteAuthenticationState, 
            CustomUserAccount, CustomAccountFactory>();
    
  • AddMsalAuthentication:

    using Microsoft.AspNetCore.Components.WebAssembly.Authentication;
    
    ...
    
    builder.Services.AddMsalAuthentication<RemoteAuthenticationState, 
        CustomUserAccount>(options =>
        {
            ...
        })
        .AddAccountClaimsPrincipalFactory<RemoteAuthenticationState, 
            CustomUserAccount, CustomAccountFactory>();
    
  • AddApiAuthorization:

    using Microsoft.AspNetCore.Components.WebAssembly.Authentication;
    
    ...
    
    builder.Services.AddApiAuthorization<RemoteAuthenticationState, 
        CustomUserAccount>(options =>
        {
            ...
        })
        .AddAccountClaimsPrincipalFactory<RemoteAuthenticationState, 
            CustomUserAccount, CustomAccountFactory>();
    

biztonsági csoportok és szerepkörök ME-ID egyéni felhasználói fiókosztálysal

További példa a ME-ID biztonsági csoportokkal, a ME-ID rendszergazdai szerepkörökkel és egy egyéni felhasználói fiókosztállyal kapcsolatban az ASP.NET Core és a Microsoft Entra azonosítócsoportokkal és szerepkörökkel témájában található.

Előzetes rendszerezés hitelesítéssel

A hitelesítést és engedélyezést igénylő tartalom előzetes szabályozása jelenleg nem támogatott. Miután követte az útmutatást az Blazor WebAssembly egyik biztonsági alkalmazás témakörében, az alábbi utasításokat követve hozzon létre egy olyan alkalmazást, amely:

  • Előre renderelt útvonalak, amelyekhez nincs szükség engedélyezésre.
  • Nem rendereli elő azokat az útvonalakat, amelyekhez engedély szükséges.

Client projekt fájljához a Program gyakori szolgáltatásregisztrációkat külön metódusba csoportosítsa (például hozzon létre egy metódust a ConfigureCommonServices projekt Client fájljában). A gyakori szolgáltatások azok, amelyeket a fejlesztő regisztrál az ügyfél- és a kiszolgálóprojektek általi használatra.

public static void ConfigureCommonServices(IServiceCollection services)
{
    services.Add...;
}

A Program fájlban:

var builder = WebAssemblyHostBuilder.CreateDefault(args);
...

builder.Services.AddScoped( ... );

ConfigureCommonServices(builder.Services);

await builder.Build().RunAsync();

A Server projekt Program fájlban regisztrálja a következő további szolgáltatásokat, és hívja ConfigureCommonServices-t.

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);

A Server projekt metódusában a következő további szolgáltatásokat regisztrálja, és hívja meg a Startup.ConfigureServices-t a ConfigureCommonServices után:

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);
}

A keretrendszerkiszolgáló-hitelesítésszolgáltatóval (Blazor) kapcsolatos ServerAuthenticationStateProvider további információkért lásd ASP.NET alapvető Blazor hitelesítést és engedélyezést.

Server projekt Pages/_Host.cshtml fájljában cserélje le a Component tag segédet (<component ... />) a következőre:

<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>

Az előző példában:

  • A {CLIENT APP ASSEMBLY NAME} helykitöltő az ügyfélalkalmazás összeállításának neve (például BlazorSample.Client).
  • Az elérési út szegmensének /authentication feltételes ellenőrzése:
    • Elkerüli a hitelesítési útvonalak előrendelését (render-mode="WebAssembly").
    • Előrenderelések (render-mode="WebAssemblyPrerendered") a nem hitelesítési útvonalakhoz.

Üzemeltetett alkalmazások és külső bejelentkezési szolgáltatók beállításai

Ha egy üzemeltetett Blazor WebAssembly alkalmazást külső szolgáltatóval hitelesít és engedélyez, számos lehetőség áll rendelkezésre a felhasználó hitelesítésére. Az, hogy melyiket választja, az a forgatókönyvtől függ.

További információért lásd: Az ASP.NET Core-ban további jogcímek és jogkivonatok perzisztálása külső szolgáltatóktól.

Felhasználók hitelesítése a védett külső API-k meghívásához

Hitelesítse a felhasználót egy ügyféloldali OAuth-folyamattal a külső API-szolgáltatón:

builder.services.AddOidcAuthentication(options => { ... });

Ebben a forgatókönyvben:

  • Az alkalmazást üzemeltető kiszolgáló nem játszik szerepet.
  • A kiszolgálón lévő API-k nem védhetők.
  • Az alkalmazás csak védett külső API-kat hívhat meg.

Felhasználók hitelesítése külső szolgáltatóval, és védett API-k meghívása a gazdagépkiszolgálón és a külső félen

Konfigurálás Identity külső bejelentkezési szolgáltatóval. Szerezze be a külső API-hozzáféréshez szükséges jogkivonatokat, és tárolja őket.

Amikor egy felhasználó bejelentkezik, Identity a hitelesítési folyamat részeként gyűjti a hozzáférési és frissítési jogkivonatokat. Ezen a ponton számos megközelítés érhető el a külső API-k felé irányuló API-hívásokhoz.

Harmadik fél hozzáférési jogkivonatának lekérése kiszolgálói hozzáférési jogkivonat használatával

A kiszolgálón létrehozott hozzáférési jogkivonat használatával kérje le a külső hozzáférési jogkivonatot egy kiszolgálói API-végpontról. Ebből a harmadik fél általi hozzáférési jogkivonat segítségével közvetlenül az ügyfél alkalmazásából hívhatja meg a külső API-erőforrásokat Identity.

Ezt a megközelítést nem javasoljuk. Ehhez a megközelítéshez úgy kell kezelni a külső hozzáférési jogkivonatot, mintha egy nyilvános ügyfélhez lett volna létrehozva. OAuth-értelemben a nyilvános alkalmazás nem rendelkezik titkos ügyfélkóddal, mert nem megbízható a titkos kódok biztonságos tárolásához, és a hozzáférési jogkivonat egy bizalmas ügyfél számára jön létre. A bizalmas ügyfél olyan ügyfél, amely rendelkezik titkos ügyfélkóddal, és feltételezzük, hogy képes biztonságosan tárolni a titkos kulcsokat.

  • A külső hozzáférési jogkivonat további hatóköröket adhat a bizalmas műveletek végrehajtásához azon a tényen alapulva, hogy a harmadik fél egy megbízhatóbb ügyfél számára adta ki a jogkivonatot.
  • Hasonlóképpen, a frissítési jogkivonatokat nem szabad olyan ügyfélnek kiadni, amely nem megbízható, mivel ezzel korlátlan hozzáférést biztosít az ügyfélnek, kivéve, ha más korlátozások lépnek életbe.

API-hívások indítása az ügyfélről a kiszolgálói API-ra külső API-k meghívásához

API-hívást kezdeményezhet az ügyféltől a kiszolgálói API-hoz. A kiszolgálóról kérje le a külső API-erőforrás hozzáférési jogkivonatát, és adja ki a szükséges hívásokat.

Ezt a megközelítést javasoljuk. Bár ehhez a megközelítéshez további hálózati ugrásra van szükség a kiszolgálón egy külső API meghívásához, ez végső soron biztonságosabb élményt eredményez:

  • A kiszolgáló tárolhatja a frissítési jogkivonatokat, és meggyőződhet arról, hogy az alkalmazás nem veszíti el a hozzáférést a külső erőforrásokhoz.
  • Az alkalmazás nem tudja kiszivárogtatni a hozzáférési jogkivonatokat a kiszolgálóról, amely bizalmasabb engedélyeket tartalmazhat.

OpenID Connect (OIDC) 2.0-s verziójú végpontok használata

A hitelesítési kódtár és Blazor a projektsablonok OpenID Connect (OIDC) 1.0-s verziójú végpontokat használnak. V2.0-s végpont használatához konfigurálja a JWT Bearer JwtBearerOptions.Authority beállítást. Az alábbi példában a ME-ID a 2.0-s verzióhoz van konfigurálva egy v2.0 szegmens hozzáfűzésével a Authority tulajdonsághoz:

using Microsoft.AspNetCore.Authentication.JwtBearer;

...

builder.Services.Configure<JwtBearerOptions>(
    JwtBearerDefaults.AuthenticationScheme, 
    options =>
    {
        options.Authority += "/v2.0";
    });

Másik lehetőségként a beállítás az alkalmazásbeállítások (appsettings.json) fájlban is megadható:

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

Ha nem megfelelő egy szegmens csatolása a hatósághoz az alkalmazás OIDC-szolgáltatójánál, mint például a nemME-ID szolgáltatók esetében, akkor állítsa be közvetlenül a Authority tulajdonságot. Állítsa be a tulajdonságot vagy a JwtBearerOptions-ban, vagy az alkalmazásbeállítások fájljában (appsettings.json) a Authority kulccsal.

Az azonosító jogkivonatában szereplő jogcímek listája megváltozik a 2.0-s verziójú végpontok esetében. A Microsoft a módosításokkal kapcsolatos dokumentációját visszavonta, de az azonosító jogkivonatban lévő jogcímekre vonatkozó útmutatás az azonosító jogkivonat jogcímeinek hivatkozásábanérhető el.

GRPC konfigurálása és használata összetevőkben

Az alkalmazás Blazor WebAssembly konfigurálása az ASP.NET Core gRPC keretrendszer használatára:

Note

Az előrenderelés alapértelmezés szerint engedélyezve van Blazor Web App-ekben, ezért figyelembe kell vennie az összetevő renderelését először a szerverről, majd az ügyféltől. Minden előre beállított állapotnak át kell haladnia az ügyfélhez, hogy újra felhasználható legyen. További információ: ASP.NET Core Blazor előre beállított állapotmegőrzés.

Note

Az előzetes renderelés alapértelmezés szerint engedélyezve van a hosztolt Blazor WebAssembly alkalmazásokban, ezért figyelembe kell vennie, hogy az összetevő először a kiszolgálóról, majd az ügyfélről kerül megjelenítésre. Minden előre beállított állapotnak át kell haladnia az ügyfélhez, hogy újra felhasználható legyen. További információ: ASP.NET Core-összetevők Razor integrálása az MVC-vel vagy Razor a Pages szolgáltatással üzemeltetett Blazor WebAssembly megoldásokban.

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);
});

Az ügyfélalkalmazás egy összetevője gRPC-hívásokat kezdeményezhet a gRPC-ügyfél (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();
        }
    }
}

A Status.DebugException tulajdonság használatához használjon 2.30.0-s vagy újabb verziót a Grpc.Net.Client esetén.

További információ: gRPC-Web ASP.NET Core gRPC-alkalmazásokban.

AuthenticationService Az implementáció cseréje

A következő alszakaszok a csere módját ismertetik:

  • Bármilyen JavaScript-implementáció AuthenticationService .
  • A JavaScripthez készült Microsoft Authentication Library (MSAL.js).

JavaScript AuthenticationService implementációk cseréje

Hozzon létre egy JavaScript-kódtárat az egyéni hitelesítési adatok kezeléséhez.

Warning

Az ebben a szakaszban található útmutató az alapértelmezett RemoteAuthenticationService<TRemoteAuthenticationState,TAccount,TProviderOptions>implementáció részleteit ismerteti. Az ebben a szakaszban szereplő TypeScript-kód kifejezetten a .NET 7 ASP.NET Core-ra vonatkozik, és a ASP.NET Core hamarosan megjelenő kiadásaiban értesítés nélkül változhat.

// .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 };
};

A tár importálásához távolítsa el az eredeti <script> címkét, és adjon hozzá egy <script> olyan címkét, amely betölti az egyéni tárat. Az alábbi példa bemutatja, hogyan cseréljük le az alapértelmezett <script> címkét egy olyanra, amely betölti a CustomAuthenticationService.js nevű kódtárat a wwwroot/js mappából.

A wwwroot/index.html szkript (Blazor) előtt _framework/blazor.webassembly.js a záró </body> címkén belül:

- <script src="_content/Microsoft.Authentication.WebAssembly.Msal/AuthenticationService.js"></script>
+ <script src="js/CustomAuthenticationService.js"></script>

További információt a AuthenticationService.ts GitHub-adattárban találdotnet/aspnetcore.

Note

A .NET referenciaforrásra mutató dokumentációs hivatkozások általában betöltik az adattár alapértelmezett ágát, amely a .NET következő kiadásának aktuális fejlesztését jelöli. Egy adott kiadás címkéjének kiválasztásához használja az Ágak vagy címkék közötti váltás legördülő listát. További információ: A ASP.NET Core-forráskód (dotnet/AspNetCore.Docs #26205) verziócímkéjének kiválasztása.

Cserélje le a JavaScripthez készült Microsoft Authentication Library-t (MSAL.js)

Ha egy alkalmazáshoz a JavaScripthez készült Microsoft Authentication Library (MSAL.js)egyéni verziója szükséges, hajtsa végre a következő lépéseket:

  1. Ellenőrizze, hogy a rendszer rendelkezik-e a legújabb fejlesztői .NET SDK-val, vagy szerezze be és telepítse a legújabb fejlesztői SDK-t a .NET SDK-ból: Telepítők és bináris fájlok. Ehhez a forgatókönyvhöz nincs szükség belső NuGet-hírcsatornák konfigurálásához.
  2. Állítsa be a dotnet/aspnetcore GitHub-adattárat a fejlesztéshez a Build ASP.NET Core forrásból című dokumentációját követve. Elágaztathatja és klónozhatja vagy letöltheti a dotnet/aspnetcore GitHub-adattár ZIP-archívumát.
  3. Nyissa meg a src/Components/WebAssembly/Authentication.Msal/src/Interop/package.json fájlt, és állítsa be a kívánt verziót @azure/msal-browser. A kiadott verziók listájáért látogasson el az @azure/msal-browser npm webhelyére , és válassza a Verziók lapot.
  4. Hozza létre a Authentication.Msal projektet a src/Components/WebAssembly/Authentication.Msal/src mappában egy yarn build parancshéjban található paranccsal.
  5. Ha az alkalmazás tömörített objektumokat (Brotli/Gzip) használ, tömörítse a Interop/dist/Release/AuthenticationService.js fájlt.
  6. Másolja a AuthenticationService.js fájlt és a fájl tömörített verzióit (.br/.gz), ha előállították, a Interop/dist/Release mappából az alkalmazás publish/wwwroot/_content/Microsoft.Authentication.WebAssembly.Msal közzétett eszközök mappájába.

Egyéni szolgáltatói beállítások átadása

Adjon meg egy osztályt az adatoknak a mögöttes JavaScript-kódtárnak való továbbításához.

Important

Az osztály szerkezetének meg kell egyeznie azzal, amit a kódtár elvár a JSON szerializálásakor System.Text.Json.

Az alábbi példa egy ProviderOptions hipotetikus egyéni szolgáltatói kódtár elvárásainak megfelelő attribútumokkal rendelkezőJsonPropertyName osztályt mutat be:

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; }
}

Regisztrálja a szolgáltatói beállításokat a DI-rendszeren belül, és konfigurálja a megfelelő értékeket:

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 = "...";
    });

Az előző példa az átirányítási URI-kat normál sztringkonstansokkal állítja be. A következő alternatívák érhetők el:

További erőforrások