stato di autenticazione di ASP.NET Core Blazor

Nota

Questa non è la versione più recente di questo articolo. Per la versione corrente, vedere la versione .NET 10 di questo articolo.

Avviso

Questa versione di ASP.NET Core non è più supportata. Per altre informazioni, vedere i criteri di supporto di .NET e .NET Core. Per la versione corrente, vedere la versione .NET 10 di questo articolo.

Questo articolo illustra come creare un provider di stato di autenticazione personalizzato e ricevere notifiche di modifica dello stato di autenticazione utente nel codice.

Gli approcci generali adottati per le app lato server e lato client Blazor sono simili, ma differiscono nelle rispettive implementazioni, quindi questo articolo alterna app lato server Blazor e app lato client Blazor. Usare il selettore pivot nella parte superiore dell'articolo per modificare il pivot dell'articolo in modo che corrisponda al tipo di Blazor progetto usato:

  • App lato server Blazor (Server pivot): Blazor Server per .NET 7 o versioni precedenti e il progetto server di un'app Blazor Web App per .NET 8 o versioni successive.
  • App lato Blazor client (Blazor WebAssembly pivot): Blazor WebAssembly per tutte le versioni di .NET o il progetto .Client di un Blazor Web App per .NET 8 o versioni successive.

Classe astratta AuthenticationStateProvider

Il Blazor framework include una classe astratta AuthenticationStateProvider per fornire informazioni sullo stato di autenticazione dell'utente corrente con i membri seguenti:

Implementare un AuthenticationStateProvider personalizzato

L'app deve fare riferimento al Microsoft.AspNetCore.Components.Authorization pacchetto NuGet, che fornisce supporto per l'autenticazione e l'autorizzazione per Blazor le app.

Nota

Per indicazioni sull'aggiunta di pacchetti alle app .NET, vedere gli articoli sotto Installare e gestire pacchetti in Flusso di lavoro dell'utilizzo di pacchetti (documentazione di NuGet). Confermare le versioni corrette del pacchetto all'indirizzo NuGet.org.

Configura nel file Program i seguenti servizi di autenticazione, autorizzazione e stato di autenticazione a catena.

Quando si crea un'app Blazor da uno dei Blazor modelli di progetto con autenticazione abilitata, l'app è preconfigurata con le registrazioni del servizio seguenti, che include l'esposizione dello stato di autenticazione come parametro a catena. Per altre informazioni, vedere autenticazione e autorizzazione di ASP.NET Core Blazor, con informazioni aggiuntive presentate nella sezione dell'articolo Personalizzare il contenuto non autorizzato con il Router componente.

using Microsoft.AspNetCore.Components.Authorization;

...

builder.Services.AddAuthorization();
builder.Services.AddCascadingAuthenticationState();

Configurare i servizi di autenticazione e autorizzazione nel Program file.

Quando si crea un'app Blazor da uno dei Blazor modelli di progetto con autenticazione abilitata, l'app include la registrazione del servizio seguente.

using Microsoft.AspNetCore.Components.Authorization;

...

builder.Services.AddAuthorization();

Configurare i servizi di autenticazione e autorizzazione in Startup.ConfigureServices di Startup.cs.

Quando si crea un'app Blazor da uno dei Blazor modelli di progetto con autenticazione abilitata, l'app include la registrazione del servizio seguente.

using Microsoft.AspNetCore.Components.Authorization;

...

services.AddAuthorization();

Nelle Blazor WebAssembly applicazioni (tutte le versioni di .NET) o nel progetto .Client di un Blazor Web App (.NET 8 o versioni successive), configurare i servizi di autenticazione, autorizzazione e stato di autenticazione a cascata nel file Program.

Quando si crea un'app Blazor da uno dei Blazor modelli di progetto con autenticazione abilitata, l'app è preconfigurata con le registrazioni del servizio seguenti, che include l'esposizione dello stato di autenticazione come parametro a catena. Per altre informazioni, vedere autenticazione e autorizzazione di ASP.NET Core Blazor, con informazioni aggiuntive presentate nella sezione dell'articolo Personalizzare il contenuto non autorizzato con il Router componente.

using Microsoft.AspNetCore.Components.Authorization;

...

builder.Services.AddAuthorizationCore();
builder.Services.AddCascadingAuthenticationState();

Configurare i servizi di autenticazione e autorizzazione nel Program file.

Quando si crea un'app Blazor da uno dei Blazor modelli di progetto con autenticazione abilitata, l'app include la registrazione del servizio seguente.

using Microsoft.AspNetCore.Components.Authorization;

...

builder.Services.AddAuthorizationCore();

Sottoclasse AuthenticationStateProvider e override GetAuthenticationStateAsync per creare lo stato di autenticazione dell'utente. Nell'esempio seguente tutti gli utenti vengono autenticati con il nome utente mrfibuli.

CustomAuthStateProvider.cs:

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

public class CustomAuthStateProvider : AuthenticationStateProvider
{
    public override Task<AuthenticationState> GetAuthenticationStateAsync()
    {
        var identity = new ClaimsIdentity(
        [
            new Claim(ClaimTypes.Name, "mrfibuli"),
        ], "Custom Authentication");

        var user = new ClaimsPrincipal(identity);

        return Task.FromResult(new AuthenticationState(user));
    }
}

Nota

Il codice precedente che crea un nuovo ClaimsIdentity usa l'inizializzazione semplificata della raccolta introdotta con C# 12 (.NET 8). Per altre informazioni, vedere Espressioni di raccolta - Riferimenti al linguaggio C#.

Il CustomAuthStateProvider servizio viene registrato nel Program file. Registrare il servizio con ambito definito con AddScoped:

builder.Services.AddScoped<AuthenticationStateProvider, CustomAuthStateProvider>();

In un'app Blazor Server, registrare il servizio scopedAddScopeddopo la chiamata a AddServerSideBlazor.

builder.Services.AddServerSideBlazor();

builder.Services.AddScoped<AuthenticationStateProvider, CustomAuthStateProvider>();

In un'app Blazor Server, registrare il servizio come scopedAddScopeddopo la chiamata a AddServerSideBlazor:

services.AddServerSideBlazor();

services.AddScoped<AuthenticationStateProvider, CustomAuthStateProvider>();

Il CustomAuthStateProvider servizio viene registrato nel Program file. Registrare il servizio singleton con AddSingleton:

builder.Services.AddSingleton<AuthenticationStateProvider, CustomAuthStateProvider>();

Se non è presente, aggiungere un'istruzione @using al file delle importazioni (_Imports.razor) per rendere disponibile lo spazio dei nomi Microsoft.AspNetCore.Components.Authorization in tutti i componenti:

@using Microsoft.AspNetCore.Components.Authorization;

Confermare o modificare il componente di visualizzazione del percorso in AuthorizeRouteView nella definizione del componente Router. La posizione del Router componente varia a seconda del tipo di app. Usare la ricerca per individuare il componente se non si è a conoscenza del relativo percorso nel progetto.

<Router ...>
    <Found ...>
        <AuthorizeRouteView RouteData="routeData" 
            DefaultLayout="typeof(Layout.MainLayout)" />
        ...
    </Found>
</Router>

Nota

Quando si crea un'app Blazor da uno dei Blazor modelli di progetto con l'autenticazione abilitata, l'app include il AuthorizeRouteView componente . Per altre informazioni, vedere autenticazione e autorizzazione di ASP.NET Core Blazor con informazioni aggiuntive presentate nella sezione Personalizzare il contenuto per utenti non autorizzati con il componente Router dell'articolo.

Dove si trova il Router componente:

La posizione del Router componente varia a seconda del tipo di app. Usare la ricerca per individuare il componente se non si è a conoscenza del relativo percorso nel progetto.

<CascadingAuthenticationState>
    <Router ...>
        <Found ...>
            <AuthorizeRouteView RouteData="routeData" 
                DefaultLayout="typeof(MainLayout)" />
            ...
        </Found>
    </Router>
</CascadingAuthenticationState>

Nota

Quando si crea un'app Blazor usando uno dei modelli di progetto Blazor con l'autenticazione abilitata, l'app include i componenti AuthorizeRouteView e CascadingAuthenticationState. Per altre informazioni, vedere autenticazione e autorizzazione di ASP.NET Core Blazor, con informazioni aggiuntive presentate nella sezione dell'articolo Personalizzare il contenuto non autorizzato con il Router componente.

Il componente di esempio AuthorizeView seguente illustra il nome dell'utente autenticato:

<AuthorizeView>
    <Authorized>
        <p>Hello, @context.User.Identity?.Name!</p>
    </Authorized>
    <NotAuthorized>
        <p>You're not authorized.</p>
    </NotAuthorized>
</AuthorizeView>

Per informazioni sull'uso di AuthorizeView, vedere Autenticazione e autorizzazione in ASP.NET Core Blazor.

Notifiche di modifica dello stato di autenticazione

Un elemento personalizzato AuthenticationStateProvider può richiamare NotifyAuthenticationStateChanged sulla classe base AuthenticationStateProvider per notificare ai componenti che ne fanno uso il cambiamento dello stato di autenticazione, in modo che venga eseguito nuovamente il rendering.

L'esempio seguente si basa sull'implementazione di un AuthenticationStateProvider personalizzato seguendo le indicazioni riportate nella sezione Implementare un AuthenticationStateProvider personalizzato presentata in precedenza in questo articolo. Se sono già state seguite le indicazioni riportate in questa sezione, la seguente CustomAuthStateProvider sostituisce quella illustrata nella sezione .

L'implementazione seguente CustomAuthStateProvider espone un metodo personalizzato, AuthenticateUser, per accedere a un utente e notificare ai consumer la modifica dello stato di autenticazione.

CustomAuthStateProvider.cs:

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

public class CustomAuthStateProvider : AuthenticationStateProvider
{
    public override Task<AuthenticationState> GetAuthenticationStateAsync()
    {
        var identity = new ClaimsIdentity();
        var user = new ClaimsPrincipal(identity);

        return Task.FromResult(new AuthenticationState(user));
    }

    public void AuthenticateUser(string userIdentifier)
    {
        var identity = new ClaimsIdentity(
        [
            new Claim(ClaimTypes.Name, userIdentifier),
        ], "Custom Authentication");

        var user = new ClaimsPrincipal(identity);

        NotifyAuthenticationStateChanged(
            Task.FromResult(new AuthenticationState(user)));
    }
}

Nota

Il codice precedente che crea un nuovo ClaimsIdentity usa l'inizializzazione semplificata della raccolta introdotta con C# 12 (.NET 8). Per altre informazioni, vedere Espressioni di raccolta - Riferimenti al linguaggio C#.

In un componente:

  • Inserisci AuthenticationStateProvider.
  • Aggiungere un campo per contenere l'identificatore dell'utente.
  • Aggiungere un pulsante e un metodo per fare il cast di AuthenticationStateProvider a CustomAuthStateProvider e chiamare AuthenticateUser passando l'identificatore dell'utente.
@inject AuthenticationStateProvider AuthenticationStateProvider

<input @bind="userIdentifier" />
<button @onclick="SignIn">Sign in</button>

<AuthorizeView>
    <Authorized>
        <p>Hello, @context.User.Identity?.Name!</p>
    </Authorized>
    <NotAuthorized>
        <p>You're not authorized.</p>
    </NotAuthorized>
</AuthorizeView>

@code {
    public string userIdentifier = string.Empty;

    private void SignIn()
    {
        ((CustomAuthStateProvider)AuthenticationStateProvider)
            .AuthenticateUser(userIdentifier);
    }
}

L'approccio precedente può essere migliorato per attivare le notifiche delle modifiche dello stato di autenticazione tramite un servizio personalizzato. La seguente classe CustomAuthenticationService mantiene l'oggetto ClaimsPrincipal dell'utente corrente in un campo di supporto (currentUser) con un evento (UserChanged) a cui il provider dello stato di autenticazione può sottoscriversi e che chiama NotifyAuthenticationStateChanged. Con la configurazione aggiuntiva descritta più avanti in questa sezione, è possibile iniettare CustomAuthenticationService in un componente con una logica che imposta CurrentUser in modo da attivare l'evento UserChanged.

CustomAuthenticationService.cs:

using System.Security.Claims;

public class CustomAuthenticationService
{
    public event Action<ClaimsPrincipal>? UserChanged;
    private ClaimsPrincipal? currentUser;

    public ClaimsPrincipal CurrentUser
    {
        get { return currentUser ?? new(); }
        set
        {
            currentUser = value;

            if (UserChanged is not null)
            {
                UserChanged(currentUser);
            }
        }
    }
}

Nel file Program, registrare CustomAuthenticationService nel contenitore di iniezione delle dipendenze:

builder.Services.AddScoped<CustomAuthenticationService>();

In Startup.ConfigureServices di Startup.cs, registrare CustomAuthenticationService nel contenitore per l'iniezione delle dipendenze:

services.AddScoped<CustomAuthenticationService>();

Nel file Program, registrare CustomAuthenticationService nel contenitore di dependency injection:

builder.Services.AddSingleton<CustomAuthenticationService>();

Il codice seguente CustomAuthStateProvider sottoscrive l'evento CustomAuthenticationService.UserChanged. Il GetAuthenticationStateAsync metodo restituisce lo stato di autenticazione dell'utente. Inizialmente, lo stato di autenticazione è basato sul valore di CustomAuthenticationService.CurrentUser. Quando l'utente cambia, viene creato un nuovo stato di autenticazione per il nuovo utente (new AuthenticationState(newUser)) per le chiamate a GetAuthenticationStateAsync:

using Microsoft.AspNetCore.Components.Authorization;

public class CustomAuthStateProvider : AuthenticationStateProvider
{
    private AuthenticationState authenticationState;

    public CustomAuthStateProvider(CustomAuthenticationService service)
    {
        authenticationState = new AuthenticationState(service.CurrentUser);

        service.UserChanged += (newUser) =>
        {
            authenticationState = new AuthenticationState(newUser);
            NotifyAuthenticationStateChanged(Task.FromResult(authenticationState));
        };
    }

    public override Task<AuthenticationState> GetAuthenticationStateAsync() =>
        Task.FromResult(authenticationState);
}

Il metodo del componente SignIn seguente crea un oggetto ClaimsPrincipal per l'identificatore utente da impostare in CustomAuthenticationService.CurrentUser:

@using System.Security.Claims
@inject CustomAuthenticationService AuthService

<input @bind="userIdentifier" />
<button @onclick="SignIn">Sign in</button>

<AuthorizeView>
    <Authorized>
        <p>Hello, @context.User.Identity?.Name!</p>
    </Authorized>
    <NotAuthorized>
        <p>You're not authorized.</p>
    </NotAuthorized>
</AuthorizeView>

@code {
    public string userIdentifier = string.Empty;

    private void SignIn()
    {
        var currentUser = AuthService.CurrentUser;

        var identity = new ClaimsIdentity(
            [
                new Claim(ClaimTypes.Name, userIdentifier),
            ],
            "Custom Authentication");

        var newUser = new ClaimsPrincipal(identity);

        AuthService.CurrentUser = newUser;
    }
}

Nota

Il codice precedente che crea un nuovo ClaimsIdentity usa l'inizializzazione semplificata della raccolta introdotta con C# 12 (.NET 8). Per altre informazioni, vedere Espressioni di raccolta - Riferimenti al linguaggio C#.

Risorse aggiuntive