Autenticazione e autorizzazione per ASP.NET Core Blazor

Nota

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

Avviso

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

Importante

Queste informazioni si riferiscono a un prodotto non definitive che può essere modificato in modo sostanziale prima che venga rilasciato commercialmente. Microsoft non riconosce alcuna garanzia, espressa o implicita, in merito alle informazioni qui fornite.

Per la versione corrente, vedere la versione .NET 8 di questo articolo.

Questo articolo descrive il supporto di ASP.NET Core per la configurazione e la gestione della sicurezza nelle app Blazor.

Gli scenari di sicurezza variano tra il codice di autorizzazione che esegue il lato server e il lato client nelle Blazor app. Per il codice di autorizzazione eseguito nel server, i controlli di autorizzazione sono in grado di applicare le regole di accesso per le aree dell'app e dei componenti. Poiché l'esecuzione del codice sul lato client può essere manomessa, il codice di autorizzazione in esecuzione nel client non può essere considerato attendibile per applicare assolutamente le regole di accesso o controllare la visualizzazione del contenuto lato client.

Se l'imposizione delle regole di autorizzazione deve essere garantita, non implementare i controlli di autorizzazione nel codice lato client. Compilare un oggetto Blazor Web App che si basa solo sul rendering lato server (SSR) per i controlli di autorizzazione e l'imposizione delle regole.

Le convenzioni di autorizzazione di RazorPages non si applicano ai componenti Razor instradabili. Se un componente non instradabile Razor è incorporato in una pagina di un'app RazorPages, le convenzioni di autorizzazione della pagina influiscono indirettamente sul Razor componente insieme al rest contenuto della pagina.

Se l'imposizione delle regole di autorizzazione e la sicurezza dei dati e del codice devono essere garantiti, non sviluppare un'app sul lato client. Creare un'app Blazor Server .

Le convenzioni di autorizzazione di RazorPages non si applicano ai componenti Razor instradabili. Se un componente non instradabile Razor è incorporato in una pagina di un'app RazorPages, le convenzioni di autorizzazione della pagina influiscono indirettamente sul Razor componente insieme al rest contenuto della pagina.

ASP.NET Core Identity è progettato per funzionare nel contesto della comunicazione di richiesta e risposta HTTP, che in genere non è il modello di comunicazione client-server dell'app Blazor . Le app ASP.NET Core che usano ASP.NET Core Identity per la gestione utenti devono usare Razor Pages anziché componenti Razor per l'interfaccia utente correlata a Identity, ad esempio registrazione utente, accesso, disconnessione e altre attività di gestione utenti. La compilazione di Razor componenti che gestiscono Identity direttamente le attività è possibile per diversi scenari, ma non è consigliata o supportata da Microsoft.

Le astrazioni ASP.NET Core, come SignInManager<TUser> e UserManager<TUser>, non sono supportate nei componenti Razor. Per altre informazioni sull'uso di ASP.NET Core Identity con , vedere Scaffolding ASP.NET Core Identity in un'app lato Blazor server.Blazor

Nota

Gli esempi di codice in questo articolo adottano tipi di riferimento nullable (NRT) e l'analisi statica dello stato null del compilatore .NET, supportati in ASP.NET Core in .NET 6 o versione successiva. Quando la destinazione è ASP.NET Core 5.0 o versioni precedenti, rimuovere la designazione di tipo Null (?) dagli esempi in questo articolo.

Mantenere in modo sicuro dati e credenziali sensibili

Non archiviare segreti dell'app, stringa di connessione, credenziali, password, numeri di identificazione personale (PIN), codice .NET/C# privato o chiavi/token privati nel codice lato client, che è sempre non sicuro. Il codice lato Blazor client deve accedere a servizi e database sicuri tramite un'API Web sicura che si controlla.

Negli ambienti di test/gestione temporanea e produzione, il codice lato Blazor server e le API Web devono usare flussi di autenticazione sicuri che evitano di mantenere le credenziali all'interno del codice del progetto o dei file di configurazione. Al di fuori dei test di sviluppo locali, è consigliabile evitare l'uso di variabili di ambiente per archiviare i dati sensibili, perché le variabili di ambiente non sono l'approccio più sicuro. Per i test di sviluppo locali, lo strumento Secret Manager è consigliato per proteggere i dati sensibili. Per ulteriori informazioni, vedi le seguenti risorse:

Per lo sviluppo e il test locali sul lato client e sul lato server, usare lo strumento Secret Manager per proteggere le credenziali sensibili.

Identità gestite per i servizi di Microsoft Azure

Per i servizi di Microsoft Azure, è consigliabile usare le identità gestite. Le identità gestite eseguono l'autenticazione sicura ai servizi di Azure senza archiviare le credenziali nel codice dell'app. Per ulteriori informazioni, vedi le seguenti risorse:

Supporto antiforgerato

Il Blazor modello:

Il componente esegue il AntiforgeryToken rendering di un token antiforgery come campo nascosto e questo componente viene aggiunto automaticamente alle istanze del modulo (EditForm). Per altre informazioni, vedere ASP.NET Panoramica dei moduli principaliBlazor.

Il AntiforgeryStateProvider servizio fornisce l'accesso a un token antiforgery associato alla sessione corrente. Inserire il servizio e chiamare il GetAntiforgeryToken() relativo metodo per ottenere l'oggetto corrente AntiforgeryRequestToken. Per altre informazioni, vedere Chiamare un'API Web da un'app ASP.NET CoreBlazor.

Blazor archivia i token di richiesta nello stato del componente, che garantisce che i token antiforgery siano disponibili per i componenti interattivi, anche quando non hanno accesso alla richiesta.

Nota

La mitigazione antiforgery è necessaria solo quando si inviano i dati del modulo al server codificati come application/x-www-form-urlencoded, multipart/form-datao text/plain poiché sono gli unici tipi di modulo validi.

Per ulteriori informazioni, vedi le seguenti risorse:

Autenticazione

Blazor usa i meccanismi di autenticazione di base di ASP.NET esistenti per stabilire l'oggetto dell'utente identity. Il meccanismo esatto dipende dal modo in cui l'app Blazor è ospitata, lato server o lato client.

Autenticazione lato Blazor server

Il lato Blazor server con rendering interattivo opera su una SignalR connessione con il client. L'autenticazione nelle app basate su SignalR viene gestita quando viene stabilita la connessione. L'autenticazione può essere basata su un cookie o su un altro token di connessione, ma l'autenticazione viene gestita tramite l'hub SignalR e interamente all'interno del circuito.

Il servizio predefinito o personalizzato AuthenticationStateProvider ottiene i dati dello stato di autenticazione da ASP.NET Core.HttpContext.User Questo è il modo in cui lo stato di autenticazione si integra con i meccanismi di autenticazione ASP.NET Core esistenti.

Per altre informazioni sull'autenticazione lato server, vedere Proteggere ASP.NET app lato Blazor server core.

IHttpContextAccessor/HttpContext nei Razor componenti

IHttpContextAccessor è necessario evitare il rendering interattivo perché non è disponibile un valore valido HttpContext .

IHttpContextAccessor può essere usato per i componenti di cui viene eseguito il rendering statico nel server. Tuttavia, è consigliabile evitarlo, se possibile.

HttpContext può essere usato come parametro a catena solo nei componenti radice sottoposti a rendering statico per attività generali, ad esempio l'ispezione e la modifica di intestazioni o altre proprietà nel App componente (Components/App.razor). Il valore è sempre null per il rendering interattivo.

[CascadingParameter]
public HttpContext? HttpContext { get; set; }

Per gli scenari in cui HttpContext è necessario nei componenti interattivi, è consigliabile fluire i dati tramite lo stato del componente persistente dal server. Per altre informazioni, vedere Scenari di sicurezza aggiuntivi sul lato server ASP.NET CoreBlazor.

Non usare IHttpContextAccessor/HttpContext direttamente o indirettamente nei Razor componenti delle app lato Blazor server. Blazor le app vengono eseguite all'esterno del contesto della pipeline core ASP.NET. Non HttpContext è garantito che sia disponibile all'interno di IHttpContextAccessore HttpContext non sia garantito che contenga il contesto che ha avviato l'app Blazor .

L'approccio consigliato per passare lo stato della richiesta all'app consiste nell'usare Blazor i parametri del componente radice durante il rendering iniziale dell'app. In alternativa, l'app può copiare i dati in un servizio con ambito nell'evento del ciclo di vita di inizializzazione del componente radice da usare nell'app. Per altre informazioni, vedere Scenari di sicurezza aggiuntivi sul lato server ASP.NET CoreBlazor.

Un aspetto critico della sicurezza lato Blazor server è che l'utente collegato a un determinato circuito potrebbe essere aggiornato a un certo punto dopo che il Blazor circuito è stato stabilito, ma IHttpContextAccessornon viene aggiornato. Per altre informazioni sulla gestione di questa situazione con i servizi personalizzati, vedere Scenari di sicurezza aggiuntivi sul lato server ASP.NET CoreBlazor.

Stato condiviso

Le app sul lato Blazor server sono attive in memoria server e più sessioni di app sono ospitate nello stesso processo. Per ogni sessione dell'app, Blazor avvia un circuito con il proprio ambito contenitore di inserimento delle dipendenze, pertanto i servizi con ambito sono univoci per Blazor sessione.

Avviso

Non è consigliabile che le app nello stesso stato di condivisione server usino servizi singleton, a meno che non venga eseguita un'estrema attenzione, in quanto ciò può introdurre vulnerabilità di sicurezza, ad esempio la perdita dello stato utente tra circuiti.

È possibile usare i servizi singleton con stato nelle Blazor app se sono progettati specificamente per esso. Ad esempio, l'uso di una cache di memoria singleton è accettabile perché una cache di memoria richiede una chiave per accedere a una determinata voce. Supponendo che gli utenti non abbiano il controllo sulle chiavi della cache usate con la cache, lo stato archiviato nella cache non perde i circuiti.

Per indicazioni generali sulla gestione dello stato, vedere ASP.NET Gestione dello stato coreBlazor.

Autenticazione lato client Blazor

Nelle app sul lato client, i controlli di autenticazione lato Blazor client possono essere ignorati perché tutto il codice lato client può essere modificato dagli utenti. Lo stesso vale per tutte le tecnologie delle app lato client, inclusi framework SPA JavaScript e app native per qualsiasi sistema operativo.

Aggiungere quanto segue:

Per gestire l'autenticazione, usare il servizio predefinito o personalizzato AuthenticationStateProvider .

Per altre informazioni sull'autenticazione lato client, vedere Secure ASP.NET Core Blazor WebAssembly.

Servizio AuthenticationStateProvider

AuthenticationStateProvider è il servizio sottostante usato dal AuthorizeView componente e dai servizi di autenticazione a catena per ottenere lo stato di autenticazione per un utente.

AuthenticationStateProviderè il servizio sottostante usato dal componente e CascadingAuthenticationState dal AuthorizeView componente per ottenere lo stato di autenticazione per un utente.

In genere non si usa AuthenticationStateProvider direttamente. Usare gli approcci con il componente AuthorizeView oppure Task<AuthenticationState> descritti più avanti in questo articolo. Lo svantaggio principale dell'uso diretto di AuthenticationStateProvider è che il componente non riceve alcuna notifica automaticamente se i dati relativi allo stato di autenticazione sottostanti cambiano.

Per implementare un oggetto personalizzato AuthenticationStateProvider, vedere ASP.NET stato di autenticazione core Blazor , che include indicazioni sull'implementazione delle notifiche di modifica dello stato di autenticazione utente.

Ottenere i dati dell'entità di attestazione di un utente

Il AuthenticationStateProvider servizio può fornire i dati dell'utente ClaimsPrincipal corrente, come illustrato nell'esempio seguente.

ClaimsPrincipalData.razor:

@page "/claims-principal-data"
@using System.Security.Claims
@inject AuthenticationStateProvider AuthenticationStateProvider

<h1>ClaimsPrincipal Data</h1>

<button @onclick="GetClaimsPrincipalData">Get ClaimsPrincipal Data</button>

<p>@authMessage</p>

@if (claims.Any())
{
    <ul>
        @foreach (var claim in claims)
        {
            <li>@claim.Type: @claim.Value</li>
        }
    </ul>
}

<p>@surname</p>

@code {
    private string? authMessage;
    private string? surname;
    private IEnumerable<Claim> claims = Enumerable.Empty<Claim>();

    private async Task GetClaimsPrincipalData()
    {
        var authState = await AuthenticationStateProvider
            .GetAuthenticationStateAsync();
        var user = authState.User;

        if (user.Identity is not null && user.Identity.IsAuthenticated)
        {
            authMessage = $"{user.Identity.Name} is authenticated.";
            claims = user.Claims;
            surname = user.FindFirst(c => c.Type == ClaimTypes.Surname)?.Value;
        }
        else
        {
            authMessage = "The user is NOT authenticated.";
        }
    }
}

Nell'esempio precedente:

  • ClaimsPrincipal.Claims restituisce le attestazioni dell'utente (claims) per la visualizzazione nell'interfaccia utente.
  • Riga che ottiene il cognome dell'utente (surname) con ClaimsPrincipal.FindAll un predicato per filtrare le attestazioni dell'utente.
@page "/claims-principal-data"
@using System.Security.Claims
@inject AuthenticationStateProvider AuthenticationStateProvider

<h1>ClaimsPrincipal Data</h1>

<button @onclick="GetClaimsPrincipalData">Get ClaimsPrincipal Data</button>

<p>@authMessage</p>

@if (claims.Any())
{
    <ul>
        @foreach (var claim in claims)
        {
            <li>@claim.Type: @claim.Value</li>
        }
    </ul>
}

<p>@surname</p>

@code {
    private string? authMessage;
    private string? surname;
    private IEnumerable<Claim> claims = Enumerable.Empty<Claim>();

    private async Task GetClaimsPrincipalData()
    {
        var authState = await AuthenticationStateProvider
            .GetAuthenticationStateAsync();
        var user = authState.User;

        if (user.Identity is not null && user.Identity.IsAuthenticated)
        {
            authMessage = $"{user.Identity.Name} is authenticated.";
            claims = user.Claims;
            surname = user.FindFirst(c => c.Type == ClaimTypes.Surname)?.Value;
        }
        else
        {
            authMessage = "The user is NOT authenticated.";
        }
    }
}

Se user.Identity.IsAuthenticated è true e perché l'utente è un ClaimsPrincipal, è possibile enumerare le attestazioni e valutare l'appartenenza ai ruoli.

Per altre informazioni sull'inserimento delle dipendenze e sui servizi, vedere Inserimento delle dipendenze di ASP.NET Core Blazor e Inserimento delle dipendenze in ASP.NET Core. Per informazioni su come implementare un oggetto personalizzatoAuthenticationStateProvider, vedere ASP.NET stato di autenticazione coreBlazor.

Esporre lo stato di autenticazione come un parametro a catena

Se i dati dello stato di autenticazione sono necessari per la logica procedurale, ad esempio quando si esegue un'azione attivata dall'utente, ottenere i dati dello stato di autenticazione definendo un parametro a catena di tipo>Task<AuthenticationState , come illustrato nell'esempio seguente.

CascadeAuthState.razor:

@page "/cascade-auth-state"

<h1>Cascade Auth State</h1>

<p>@authMessage</p>

@code {
    private string authMessage = "The user is NOT authenticated.";

    [CascadingParameter]
    private Task<AuthenticationState>? authenticationState { get; set; }

    protected override async Task OnInitializedAsync()
    {
        if (authenticationState is not null)
        {
            var authState = await authenticationState;
            var user = authState?.User;

            if (user?.Identity is not null && user.Identity.IsAuthenticated)
            {
                authMessage = $"{user.Identity.Name} is authenticated.";
            }
        }
    }
}
@page "/cascade-auth-state"

<h1>Cascade Auth State</h1>

<p>@authMessage</p>

@code {
    private string authMessage = "The user is NOT authenticated.";

    [CascadingParameter]
    private Task<AuthenticationState>? authenticationState { get; set; }

    protected override async Task OnInitializedAsync()
    {
        if (authenticationState is not null)
        {
            var authState = await authenticationState;
            var user = authState?.User;

            if (user?.Identity is not null && user.Identity.IsAuthenticated)
            {
                authMessage = $"{user.Identity.Name} is authenticated.";
            }
        }
    }
}

Se user.Identity.IsAuthenticated è true, è possibile enumerare le attestazioni e valutare l'appartenenza ai ruoli.

Configurare il Task<AuthenticationState> parametro a catena usando i AuthorizeRouteView servizi di stato di autenticazione a catena e .

Quando si crea un'app Blazor da uno dei Blazor modelli di progetto con autenticazione abilitata, l'app include AuthorizeRouteView e la chiamata a AddCascadingAuthenticationState illustrata nell'esempio seguente. Un'app lato Blazor client include anche le registrazioni del servizio necessarie. Altre informazioni vengono visualizzate nella sezione Personalizzare il contenuto non autorizzato con il Router componente .

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

Program Nel file registrare i servizi di stato di autenticazione a catena:

builder.Services.AddCascadingAuthenticationState();

Configurare il Task<> AuthenticationStateparametro a catena usando i AuthorizeRouteView componenti e .CascadingAuthenticationState

Quando si crea un'app Blazor da uno dei Blazor modelli di progetto con autenticazione abilitata, l'app include i AuthorizeRouteView componenti e CascadingAuthenticationState illustrati nell'esempio seguente. Un'app lato Blazor client include anche le registrazioni del servizio necessarie. Altre informazioni vengono visualizzate nella sezione Personalizzare il contenuto non autorizzato con il Router componente .

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

Nota

Con la versione di ASP.NET Core 5.0.1 e per eventuali versioni 5.x aggiuntive, il componente Router include il parametro PreferExactMatches impostato su @true. Per altre informazioni, vedere Eseguire la migrazione da ASP.NET Core 3.1 a 5.0.

In un'app sul lato Blazor client aggiungere i servizi di autorizzazione al Program file:

builder.Services.AddAuthorizationCore();

In un'app sul lato Blazor client aggiungere opzioni e servizi di autorizzazione al Program file:

builder.Services.AddOptions();
builder.Services.AddAuthorizationCore();

In un'app sul lato Blazor server i servizi per le opzioni e l'autorizzazione sono già presenti, quindi non sono necessari altri passaggi.

Autorizzazione

Dopo l'autenticazione di un utente, vengono applicate le regole di autorizzazione per controllare le operazioni consentite per un utente.

L'accesso viene in genere concesso o negato in base alle condizioni seguenti:

  • L'utente è autenticato (ha eseguito l'accesso).
  • L'utente è incluso in un ruolo.
  • L'utente ha un'attestazione.
  • I criteri sono soddisfatti.

Questi concetti sono uguali a quelli validi per un'app ASP.NET Core MVC o Razor Pages. Per altre informazioni sulla sicurezza di ASP.NET Core, vedere gli articoli in Sicurezza e Identity per ASP.NET Core.

Componente AuthorizeView

Il componente AuthorizeView visualizza in modo selettivo il contenuto dell'interfaccia utente a seconda del fatto che l'utente sia autorizzato. Questo approccio è utile quando è sufficiente visualizzare i dati per l'utente e non è necessario usare la logica procedurale dell'utenteidentity.

Il componente espone una context variabile di tipo AuthenticationState (@context nella Razor sintassi), che è possibile usare per accedere alle informazioni sull'utente connesso:

<AuthorizeView>
    <p>Hello, @context.User.Identity?.Name!</p>
</AuthorizeView>

È anche possibile fornire contenuto diverso per la visualizzazione se l'utente non è autorizzato con una combinazione dei Authorized parametri e NotAuthorized :

<AuthorizeView>
    <Authorized>
        <p>Hello, @context.User.Identity?.Name!</p>
        <p><button @onclick="HandleClick">Authorized Only Button</button></p>
    </Authorized>
    <NotAuthorized>
        <p>You're not authorized.</p>
    </NotAuthorized>
</AuthorizeView>

@code {
    private void HandleClick() { ... }
}

Anche se il AuthorizeView componente controlla la visibilità degli elementi in base allo stato di autorizzazione dell'utente, non impone la sicurezza sul gestore eventi stesso. Nell'esempio precedente il HandleClick metodo è associato solo a un pulsante visibile agli utenti autorizzati, ma nulla impedisce di richiamare questo metodo da altre posizioni. Per garantire la sicurezza a livello di metodo, implementare logica di autorizzazione aggiuntiva all'interno del gestore stesso o nell'API pertinente.

Razor i componenti di Blazor Web Apps non visualizzano <NotAuthorized> mai il contenuto quando l'autorizzazione non riesce sul lato server durante il rendering statico lato server (SSR statico). Il lato server ASP.NET core pipeline elabora l'autorizzazione nel server. Usare tecniche lato server per gestire le richieste non autorizzate. Per altre informazioni, vedere ASP.NET Modalità di rendering coreBlazor.

Avviso

Il markup e i metodi lato client associati a un AuthorizeView oggetto sono protetti solo dalla visualizzazione e dall'esecuzione nell'interfaccia utente sottoposta a rendering nelle app lato Blazor client. Per proteggere il contenuto autorizzato e i metodi sicuri sul lato Blazorclient, il contenuto viene in genere fornito da una chiamata API Web sicura e autorizzata a un'API server e mai archiviata nell'app. Per altre informazioni, vedere Chiamare un'API Web da un'app ASP.NET Core Blazor e ASP.NET scenari di sicurezza aggiuntivi coreBlazor WebAssembly.

Il contenuto di Authorized e NotAuthorized può includere elementi arbitrari, ad esempio altri componenti interattivi.

Le condizioni di autorizzazione, ad esempio i ruoli o i criteri che consentono di controllare le opzioni dell'interfaccia utente o l'accesso, sono presentate nella sezione Autorizzazione.

Se le condizioni di autorizzazione non vengono specificate, AuthorizeView usa un criterio predefinito:

  • Gli utenti autenticati (connessi) sono autorizzati.
  • Gli utenti non autenticati (disconnessi) non sono autorizzati.

Il componente AuthorizeView può essere usato nel componente NavMenu (Shared/NavMenu.razor) per visualizzare un componente NavLink (NavLink), ma si noti che questo approccio rimuove solo l'elemento di elenco dall'output di cui è stato eseguito il rendering. Non impedisce all'utente di passare al componente. Implementare l'autorizzazione separatamente nel componente di destinazione.

Autorizzazione basata sui ruoli e basata sui criteri

Il componente AuthorizeView supporta l'autorizzazione basata sui ruoli oppure basata sui criteri.

Per l'autorizzazione basata sui ruoli, usare il Roles parametro . Nell'esempio seguente, l'utente deve avere un'attestazione del ruolo per i Admin ruoli o Superuser :

<AuthorizeView Roles="Admin, Superuser">
    <p>You have an 'Admin' or 'Superuser' role claim.</p>
</AuthorizeView>

Per richiedere che un utente disponga di attestazioni di ruolo e Admin Superuser , annidare AuthorizeView i componenti:

<AuthorizeView Roles="Admin">
    <p>User: @context.User</p>
    <p>You have the 'Admin' role claim.</p>
    <AuthorizeView Roles="Superuser" Context="innerContext">
        <p>User: @innerContext.User</p>
        <p>You have both 'Admin' and 'Superuser' role claims.</p>
    </AuthorizeView>
</AuthorizeView>

Il codice precedente stabilisce un oggetto Context per il componente interno AuthorizeView per evitare un AuthenticationState conflitto di contesto. L'accesso AuthenticationState al contesto viene eseguito nell'esterno AuthorizeView con l'approccio standard per l'accesso al contesto (@context.User). Si accede al contesto interno AuthorizeView con il contesto denominato innerContext (@innerContext.User).

Per altre informazioni, incluse indicazioni sulla configurazione, vedere Autorizzazione basata sui ruoli in ASP.NET Core.

Per l'autorizzazione basata su criteri, usare il Policy parametro con un singolo nome di criteri:

<AuthorizeView Policy="Over21">
    <p>You satisfy the 'Over21' policy.</p>
</AuthorizeView>

Per gestire il caso in cui l'utente deve soddisfare uno dei diversi criteri, creare un criterio che conferma che l'utente soddisfi altri criteri.

Per gestire il caso in cui l'utente deve soddisfare contemporaneamente diversi criteri, adottare uno degli approcci seguenti:

  • Creare un criterio per AuthorizeView che conferma che l'utente soddisfi diversi altri criteri.

  • Annidare i criteri in più AuthorizeView componenti:

    <AuthorizeView Policy="Over21">
        <AuthorizeView Policy="LivesInCalifornia">
            <p>You satisfy the 'Over21' and 'LivesInCalifornia' policies.</p>
        </AuthorizeView>
    </AuthorizeView>
    

L'autorizzazione basata sulle attestazioni è un caso speciale di autorizzazione basata su criteri. Ad esempio, è possibile definire un criterio che richiede che gli utenti abbiano una determinata attestazione. Per altre informazioni, vedere Autorizzazione basata sui criteri in ASP.NET Core.

Se non viene specificato né RolesPolicy , AuthorizeView usa i criteri predefiniti:

  • Gli utenti autenticati (connessi) sono autorizzati.
  • Gli utenti non autenticati (disconnessi) non sono autorizzati.

Poiché i confronti tra stringhe .NET fanno distinzione tra maiuscole e minuscole, anche i nomi dei criteri e dei ruoli corrispondenti fanno distinzione tra maiuscole e minuscole. Ad esempio, Admin (maiuscolo A) non viene considerato come lo stesso ruolo di admin (minuscolo a).

Il caso Pascal viene in genere usato per i nomi dei ruoli e dei criteri ,ad esempio BillingAdministrator, ma l'uso del caso Pascal non è un requisito rigoroso. Sono consentiti diversi schemi di maiuscole e minuscole, come il case camel, il kebab case e il caso serpente. L'uso di spazi nei nomi di ruoli e criteri è insolito ma consentito dal framework. Ad esempio, billing administrator è un formato insolito di ruoli o nomi di criteri nelle app .NET, ma si tratta di un ruolo o un nome di criteri valido.

Contenuto visualizzato durante l'autenticazione asincrona

Blazor consente di determinare lo stato di autenticazione in modo asincrono. Lo scenario principale per questo approccio è nelle app lato Blazor client che effettuano una richiesta a un endpoint esterno per l'autenticazione.

Mentre l'autenticazione è in corso, AuthorizeView non visualizza alcun contenuto. Per visualizzare il contenuto durante l'autenticazione, assegnare il contenuto al Authorizing parametro :

<AuthorizeView>
    <Authorized>
        <p>Hello, @context.User.Identity?.Name!</p>
    </Authorized>
    <Authorizing>
        <p>You can only see this content while authentication is in progress.</p>
    </Authorizing>
</AuthorizeView>

Questo approccio non è in genere applicabile alle app lato Blazor server. Le app sul lato Blazor server conoscono lo stato di autenticazione non appena viene stabilito lo stato. Authorizing il contenuto può essere fornito nel componente di AuthorizeView un'app, ma il contenuto non viene mai visualizzato.

Attributo [Authorize]

L'attributo [Authorize] è disponibile nei Razor componenti:

@page "/"
@attribute [Authorize]

You can only see this if you're signed in.

Importante

Usare [Authorize] solo sui @page componenti raggiunti tramite il Blazor router. L'autorizzazione viene eseguita solo come un aspetto del routing e non per i componenti figlio di cui viene eseguito il rendering all'interno di una pagina. Per autorizzare la visualizzazione di parti specifiche all'interno di una pagina, usare invece AuthorizeView.

L'attributo [Authorize] supporta anche l'autorizzazione basata sui ruoli o basata sui criteri. Per l'autorizzazione basata sui ruoli, usare il parametro Roles:

@page "/"
@attribute [Authorize(Roles = "Admin, Superuser")]

<p>You can only see this if you're in the 'Admin' or 'Superuser' role.</p>

Per l'autorizzazione basata sui criteri, usare il parametro Policy:

@page "/"
@attribute [Authorize(Policy = "Over21")]

<p>You can only see this if you satisfy the 'Over21' policy.</p>

Se non viene specificato né RolesPolicy , [Authorize] usa i criteri predefiniti:

  • Gli utenti autenticati (connessi) sono autorizzati.
  • Gli utenti non autenticati (disconnessi) non sono autorizzati.

Quando l'utente non è autorizzato e se l'app non personalizza il contenuto non autorizzato con il Router componente, il framework visualizza automaticamente il messaggio di fallback seguente:

Not authorized.

Autorizzazione delle risorse

Per autorizzare gli utenti per le risorse, passare i dati di route della richiesta al parametro Resource di AuthorizeRouteView.

Router.Found Nel contenuto di una route richiesta:

<AuthorizeRouteView Resource="routeData" RouteData="routeData" 
    DefaultLayout="typeof(MainLayout)" />

Per altre informazioni sul modo in cui i dati sullo stato di autorizzazione vengono passati e usati nella logica procedurale, vedere la sezione Esporre lo stato di autenticazione come parametro a catena.

Quando AuthorizeRouteView riceve i dati di route per la risorsa, i criteri di autorizzazione hanno accesso a RouteData.PageType e RouteData.RouteValues che consentono alla logica personalizzata di prendere decisioni per l'autorizzazione.

Nell'esempio seguente viene creato un criterio EditUser in AuthorizationOptions per la configurazione del servizio di autorizzazione dell'app (AddAuthorizationCore) con la logica seguente:

  • Determinare se esiste un valore di route con una chiave id. Se la chiave esiste, il valore della route viene archiviato in value.
  • In una variabile denominata id, archiviare value come stringa o impostare un valore stringa vuoto (string.Empty).
  • Se id non è una stringa vuota, confermare che il criterio è soddisfatto (restituire true) se il valore della stringa inizia con EMP. In caso contrario, confermare che il criterio non è stato soddisfatto (restituire false).

Nel file Program:

  • Aggiungere gli spazi dei nomi per Microsoft.AspNetCore.Components e System.Linq:

    using Microsoft.AspNetCore.Components;
    using System.Linq;
    
  • Aggiungere il criterio:

    options.AddPolicy("EditUser", policy =>
        policy.RequireAssertion(context =>
        {
            if (context.Resource is RouteData rd)
            {
                var routeValue = rd.RouteValues.TryGetValue("id", out var value);
                var id = Convert.ToString(value, 
                    System.Globalization.CultureInfo.InvariantCulture) ?? string.Empty;
    
                if (!string.IsNullOrEmpty(id))
                {
                    return id.StartsWith("EMP", StringComparison.InvariantCulture);
                }
            }
    
            return false;
        })
    );
    

L'esempio precedente è un criterio di autorizzazione molto semplificato, usato semplicemente per una dimostrazione del concetto con un esempio funzionante. Per altre informazioni sulla creazione e la configurazione dei criteri di autorizzazione, vedere Autorizzazione basata su criteri in ASP.NET Core.

Nel componente EditUser seguente la risorsa in /users/{id}/edit ha un parametro di route per l'identificatore dell'utente ({id}). Il componente usa il criterio di autorizzazione EditUser precedente per determinare se il valore della route per id inizia con EMP. Se inizia id con EMP, il criterio è soddisfatto e l'accesso al componente viene autorizzato. Se id inizia con un valore diverso da EMP o se id è una stringa vuota, il criterio non è soddisfatto e il componente non viene caricato.

EditUser.razor:

@page "/users/{id}/edit"
@using Microsoft.AspNetCore.Authorization
@attribute [Authorize(Policy = "EditUser")]

<h1>Edit User</h1>

<p>The "EditUser" policy is satisfied! <code>Id</code> starts with 'EMP'.</p>

@code {
    [Parameter]
    public string? Id { get; set; }
}
@page "/users/{id}/edit"
@using Microsoft.AspNetCore.Authorization
@attribute [Authorize(Policy = "EditUser")]

<h1>Edit User</h1>

<p>The "EditUser" policy is satisfied! <code>Id</code> starts with 'EMP'.</p>

@code {
    [Parameter]
    public string? Id { get; set; }
}

Personalizzare il contenuto non autorizzato con il Router componente

Il componente Router, insieme al componente AuthorizeRouteView, consente all'app di specificare il contenuto personalizzato se:

  • L'utente non supera una condizione [Authorize] applicata al componente. Viene visualizzato il markup dell'elemento <NotAuthorized>. L'attributo [Authorize] viene presentato nella sezione Attributo [Authorize].
  • L'autorizzazione asincrona è in corso, il che significa in genere che il processo di autenticazione dell'utente è in corso. Viene visualizzato il markup dell'elemento <Authorizing>.

Importante

Blazor le funzionalità del router che visualizzano <NotAuthorized> e <NotFound> contenuto non sono operative durante il rendering statico lato server (SSR statico) perché l'elaborazione delle richieste è interamente gestita da ASP.NET elaborazione delle richieste di pipeline middleware core e Razor i componenti non vengono sottoposti a rendering per richieste non autorizzate o non valide. Usare tecniche lato server per gestire richieste non autorizzate e non valide durante ssr statici. Per altre informazioni, vedere ASP.NET Modalità di rendering coreBlazor.

<Router ...>
    <Found ...>
        <AuthorizeRouteView ...>
            <NotAuthorized>
                ...
            </NotAuthorized>
            <Authorizing>
                ...
            </Authorizing>
        </AuthorizeRouteView>
    </Found>
</Router>

Il contenuto di Authorized e NotAuthorized può includere elementi arbitrari, ad esempio altri componenti interattivi.

Nota

Il precedente richiede la registrazione dei servizi di stato di autenticazione a catena nel file dell'app Program :

builder.Services.AddCascadingAuthenticationState();
<CascadingAuthenticationState>
    <Router ...>
        <Found ...>
            <AuthorizeRouteView ...>
                <NotAuthorized>
                    ...
                </NotAuthorized>
                <Authorizing>
                    ...
                </Authorizing>
            </AuthorizeRouteView>
        </Found>
    </Router>
</CascadingAuthenticationState>

Il contenuto di NotFound, Authorized e NotAuthorized può includere elementi arbitrari, ad esempio altri componenti interattivi.

Se NotAuthorized il contenuto non è specificato, AuthorizeRouteView usa il messaggio di fallback seguente:

Not authorized.

Un'app creata dal Blazor WebAssembly modello di progetto con l'autenticazione abilitata include un RedirectToLogin componente posizionato nel <NotAuthorized> contenuto del Router componente. Quando un utente non è autenticato (context.User.Identity?.IsAuthenticated != true), il RedirectToLogin componente reindirizza il browser all'endpoint per l'autenticazione authentication/login . L'utente viene restituito all'URL richiesto dopo l'autenticazione con il identity provider.

Logica procedurale

Se l'app deve controllare le regole di autorizzazione come parte della logica procedurale, usare un parametro a catena di tipo Task<AuthenticationState> per ottenere il ClaimsPrincipal dell'utente. Task<AuthenticationState> può essere combinato con altri servizi, ad esempio IAuthorizationService, per valutare i criteri.

Nell'esempio seguente :

  • user.Identity.IsAuthenticated Esegue il codice per gli utenti autenticati (connessi).
  • user.IsInRole("admin") Esegue il codice per gli utenti nel ruolo 'Admin'.
  • Esegue (await AuthorizationService.AuthorizeAsync(user, "content-editor")).Succeeded il codice per gli utenti che soddisfano i criteri 'content-editor'.

Un'app lato Blazor server include gli spazi dei nomi appropriati quando viene creato dal modello di progetto. In un'app sul lato Blazor client verificare la presenza degli Microsoft.AspNetCore.Authorization spazi dei nomi e Microsoft.AspNetCore.Components.Authorization nel componente o nel file dell'app _Imports.razor :

@using Microsoft.AspNetCore.Authorization
@using Microsoft.AspNetCore.Components.Authorization

ProceduralLogic.razor:

@page "/procedural-logic"
@inject IAuthorizationService AuthorizationService

<h1>Procedural Logic Example</h1>

<button @onclick="@DoSomething">Do something important</button>

@code {
    [CascadingParameter]
    private Task<AuthenticationState>? authenticationState { get; set; }

    private async Task DoSomething()
    {
        if (authenticationState is not null)
        {
            var authState = await authenticationState;
            var user = authState?.User;

            if (user is not null)
            {
                if (user.Identity is not null && user.Identity.IsAuthenticated)
                {
                    // ...
                }

                if (user.IsInRole("Admin"))
                {
                    // ...
                }

                if ((await AuthorizationService.AuthorizeAsync(user, "content-editor"))
                    .Succeeded)
                {
                    // ...
                }
            }
        }
    }
}
@page "/procedural-logic"
@inject IAuthorizationService AuthorizationService

<h1>Procedural Logic Example</h1>

<button @onclick="@DoSomething">Do something important</button>

@code {
    [CascadingParameter]
    private Task<AuthenticationState>? authenticationState { get; set; }

    private async Task DoSomething()
    {
        if (authenticationState is not null)
        {
            var authState = await authenticationState;
            var user = authState?.User;

            if (user is not null)
            {
                if (user.Identity is not null && user.Identity.IsAuthenticated)
                {
                    // ...
                }

                if (user.IsInRole("Admin"))
                {
                    // ...
                }

                if ((await AuthorizationService.AuthorizeAsync(user, "content-editor"))
                    .Succeeded)
                {
                    // ...
                }
            }
        }
    }
}

Risolvere gli errori

Errori comuni:

  • Per l'autorizzazione è richiesto un parametro a catena di tipo Task<AuthenticationState>. Si consideri l'uso di CascadingAuthenticationState per fornirlo.

  • Valore null ricevuto per authenticationStateTask

È probabile che il progetto non sia stato creato usando un modello lato Blazor server con l'autenticazione abilitata.

In .NET 7 o versioni precedenti eseguire il wrapping di una <CascadingAuthenticationState> parte dell'albero dell'interfaccia utente, ad esempio intorno al Blazor router:

<CascadingAuthenticationState>
    <Router ...>
        ...
    </Router>
</CascadingAuthenticationState>

In .NET 8 o versione successiva non usare il CascadingAuthenticationState componente :

- <CascadingAuthenticationState>
      <Router ...>
          ...
      </Router>
- </CascadingAuthenticationState>

Aggiungere invece servizi di stato di autenticazione a catena alla raccolta di servizi nel Program file:

builder.Services.AddCascadingAuthenticationState();

Il CascadingAuthenticationState componente (.NET 7 o versioni precedenti) o i servizi forniti da AddCascadingAuthenticationState (.NET 8 o versione successiva) fornisce il Task<AuthenticationState> parametro a catena, che a sua volta riceve dal servizio di inserimento delle dipendenze sottostante.AuthenticationStateProvider

Informazioni personali (PII)

Microsoft usa la definizione del GDPR per i "dati personali" (GDPR 4.1) quando la documentazione illustra le informazioni personali.

PiI fa riferimento a qualsiasi informazione relativa a una persona fisica identificata o identificabile. Una persona fisica identificabile è una persona che può essere identificata, direttamente o indirettamente, con uno dei seguenti elementi:

  • Nome
  • Numero di identificazione
  • Coordinate della posizione
  • Identificatore online
  • Altri fattori specifici
    • Computer fisico
    • Fisiologico
    • Genetico
    • Mentale (psicologico)
    • Economico
    • Cultural
    • Sociale identity

Risorse aggiuntive