Condividi tramite


Autorizzazione basata sui ruoli in ASP.NET Core MVC

Quando l'identità di un utente viene creata dopo l'autenticazione, l'utente può appartenere a uno o più ruoli, riflettendo varie autorizzazioni che l'utente deve accedere ai dati ed eseguire operazioni. Ad esempio, Tracy può appartenere ai ruoli "Amministratore" e "Utente" con accesso alle pagine Web amministrative nell'app, mentre Scott può appartenere solo al ruolo "Utente" e non avere accesso a dati o operazioni amministrative. La modalità di creazione e gestione di questi ruoli dipende dall'archivio di backup del processo di autorizzazione. I ruoli vengono esposti allo sviluppatore tramite ClaimsPrincipal.IsInRole. AddRoles deve essere chiamato per aggiungere servizi di ruolo durante la configurazione del sistema di identità dell'app.

Mentre i ruoli sono attestazioni, non tutte le attestazioni sono ruoli. A seconda dell'identità emittente, un ruolo può essere una raccolta di utenti che possono avere dichiarazioni per i membri del gruppo, nonché una dichiarazione effettiva sull'identità. Tuttavia, le attestazioni devono essere informazioni su un singolo utente. L'uso dei ruoli per aggiungere attestazioni a un utente può confondere il limite tra l'utente e le singole attestazioni. Questa confusione è il motivo per cui i modelli di applicazione a pagina singola non sono progettati per i ruoli. Inoltre, per le organizzazioni che eseguono la migrazione da un sistema legacy locale, la proliferazione dei ruoli negli anni può significare che un'attestazione di ruolo può essere troppo grande per essere contenuta all'interno di un token utilizzabile da una SPA (Single Page Application). Per proteggere le applicazioni a pagina singola, vedere Usare Identity per proteggere un back-end dell'API Web per le applicazioni a pagina singola.

Questo articolo usa esempi MVC e si concentra sugli scenari MVC. Per la guida alle pagine di Blazor e Razor, vedere le risorse seguenti:

Aggiungere servizi di ruolo a Identity

Registrare i servizi di autorizzazione basati sui ruoli nel file Program passando il tipo di ruolo a AddRoles nella configurazione Identity dell'app. Il tipo di ruolo nell'esempio seguente è IdentityRole:

builder.Services.AddDefaultIdentity<IdentityUser>( ... )
    .AddRoles<IdentityRole>()
    ...

Il codice precedente richiede il Microsoft.AspNetCore.Identity.UI pacchetto NuGet e una using direttiva per Microsoft.AspNetCore.Identity.

Nei casi in cui l'app acquisisce un controllo granulare per la compilazione Identity manuale, chiamare AddRoles su AddIdentityCore:

builder.Services.AddIdentityCore<IdentityUser>()
    .AddRoles<IdentityRole>()
    ...

Registrare i servizi di autorizzazione basati sui ruoli in Startup.ConfigureServices (Startup.cs) chiamando AddRoles con il tipo di ruolo nella configurazione dell'app Identity. Il tipo di ruolo nell'esempio seguente è IdentityRole:

services.AddDefaultIdentity<IdentityUser>()
    .AddRoles<IdentityRole>()
    ...

Il codice precedente richiede il Microsoft.AspNetCore.Identity.UI pacchetto NuGet e una using direttiva per Microsoft.AspNetCore.Identity.

Nei casi in cui l'app acquisisce un controllo granulare per la compilazione Identity manuale, chiamare AddRoles su AddIdentityCore:

services.AddIdentityCore<IdentityUser>()
    .AddRoles<IdentityRole>()
    ...

Controlli di autorizzazione basati sui ruoli

Controlli di autorizzazione basati sui ruoli:

  • Sono dichiarativi e specificano i ruoli di cui l'utente corrente deve essere membro per accedere alla risorsa richiesta.
  • Vengono applicati ai controller o alle azioni all'interno di un controller.

Ad esempio, il codice seguente limita l'accesso a qualsiasi azione in un controller agli utenti membri del Administrator ruolo:

[Authorize(Roles = "Administrator")]
public class AdministrationController : Controller
{
    ...
}

È possibile specificare più ruoli come elenco delimitato da virgole. Nell'esempio seguente l'accesso è limitato agli utenti membri del HRManager ruolo o del Finance ruolo:

[Authorize(Roles = "HRManager, Finance")]
public class SalaryController : Controller
{
    ...
}

Quando vengono applicati più attributi, l'utente deve essere membro di tutti i ruoli specificati. L'esempio seguente richiede che entrambi i ruoli PowerUser e ControlPanelUser chiamino le azioni SetTime e Shutdown:

[Authorize(Roles = "PowerUser")]
[Authorize(Roles = "ControlPanelUser")]
public class ControlPanelController : Controller
{
    public IActionResult SetTime() { ... }
    public IActionResult ShutDown() { ... }
}

L'accesso a un'azione può essere limitato applicando altri attributi di autorizzazione del ruolo a livello di azione:

[Authorize(Roles = "Administrator, PowerUser")]
public class ControlPanelController : Controller
{
    public IActionResult SetTime() { ... }

    [Authorize(Roles = "Administrator")]
    public IActionResult ShutDown() { ... }
}

Nel controller precedente:

  • I membri del ruolo Administrator o del ruolo PowerUser possono accedere al controller e all'azione SetTime.
  • Solo i membri del Administrator ruolo possono accedere all'azione ShutDown .

Un controller può essere protetto ma consente comunque l'accesso anonimo e non autenticato a singole azioni con l'attributo[AllowAnonymous] :

[Authorize]
public class Control3PanelController : Controller
{
    public IActionResult SetTime() { ... }

    [AllowAnonymous]
    public IActionResult Login() { ... }
}

La corrispondenza dei ruoli è in genere sensibile alle maiuscole e minuscole perché i nomi dei ruoli vengono archiviati e confrontati utilizzando i confronti di stringhe di .NET. Ad esempio, Admin (maiuscolo A) non viene considerato come lo stesso ruolo di admin (minuscolo a). Per altre informazioni, vedere Autorizzazione basata sulle attestazioni in ASP.NET Core.

Controlli di autorizzazione basati su criteri

I requisiti dei ruoli possono essere espressi usando la sintassi dei criteri, in cui l'app registra un criterio all'avvio come parte della configurazione del servizio di autorizzazione. Nell'esempio seguente, il RequireAdministratorRole criterio specifica che tutti gli utenti devono essere nel ruolo di Administrator

builder.Services.AddAuthorizationBuilder()
    .AddPolicy("RequireAdministratorRole",
         policy => policy.RequireRole("Administrator"));

I criteri vengono applicati usando la proprietà Policysull'attributo [Authorize]:

[Authorize(Policy = "RequireAdministratorRole")]
public IActionResult Shutdown() { ... }

A differenza della corrispondenza dei ruoli, che in genere fa distinzione tra maiuscole e minuscole, la ricerca del nome dei criteri di ASP.NET Core non fa distinzione tra maiuscole e minuscole, e RequireAdministratorRole e requireadministratorrole si riferiscono allo stesso criterio.

Per specificare più ruoli consentiti in un requisito, specificare i ruoli come parametri per il RequireRole metodo . Nell'esempio seguente gli utenti sono autorizzati se appartengono ai Administratorruoli , PowerUseroBackupAdministrator :

builder.Services.AddAuthorizationBuilder()
    .AddPolicy("ElevatedRights", policy =>
          policy.RequireRole("Administrator", "PowerUser", "BackupAdministrator"));

Se si vuole che i criteri richiedano tutti i ruoli precedenti, concatenare i ruoli al generatore di criteri o specificarli singolarmente nel generatore di criteri in un'istruzione lambda.

Concatenato al generatore di criteri:

builder.Services.AddAuthorizationBuilder()
    .AddPolicy("ElevatedRights", policy => 
        policy
            .RequireRole("Administrator")
            .RequireRole("PowerUser")
            .RequireRole("BackupAdministrator"));

In alternativa, usare un'istruzione lambda:

builder.Services.AddAuthorizationBuilder()
    .AddPolicy("ElevatedRights",
        policy =>
        {
            policy.RequireRole("Administrator");
            policy.RequireRole("PowerUser");
            policy.RequireRole("BackupAdministrator");
        });

I requisiti dei ruoli possono essere espressi usando la sintassi dei criteri, in cui l'app registra un criterio all'avvio come parte della configurazione del servizio di autorizzazione. Nell'esempio seguente, il RequireAdministratorRole criterio specifica che tutti gli utenti devono essere nel ruolo di Administrator

builder.Services.AddAuthorization(options =>
{
    options.AddPolicy("RequireAdministratorRole",
        policy => policy.RequireRole("Administrator"));
});

I criteri vengono applicati usando la proprietà Policysull'attributo [Authorize]:

[Authorize(Policy = "RequireAdministratorRole")]
public IActionResult Shutdown() { ... }

Per specificare più ruoli consentiti in un requisito, specificare i ruoli come parametri per il RequireRole metodo . Nell'esempio seguente gli utenti sono autorizzati se appartengono ai Administratorruoli , PowerUseroBackupAdministrator :

builder.Services.AddAuthorization(options =>
{
    options.AddPolicy("ElevatedRights", policy =>
        policy.RequireRole("Administrator", "PowerUser", "BackupAdministrator"));
});

Se si vuole che i criteri richiedano tutti i ruoli precedenti, concatenare i ruoli al generatore di criteri o specificarli singolarmente nel generatore di criteri in un'istruzione lambda.

Concatenato al generatore di criteri:

builder.Services.AddAuthorization(options =>
{
    options.AddPolicy("ElevatedRights", policy =>
        policy
            .RequireRole("Administrator")
            .RequireRole("PowerUser")
            .RequireRole("BackupAdministrator"));
});

In alternativa, usare un'istruzione lambda:

builder.Services.AddAuthorization(options =>
{
    options.AddPolicy("ElevatedRights",
        policy =>
        {
            policy.RequireRole("Administrator");
            policy.RequireRole("PowerUser");
            policy.RequireRole("BackupAdministrator");
        });
});

I requisiti dei ruoli possono essere espressi usando la sintassi dei criteri, in cui l'app registra un criterio all'avvio come parte della configurazione del servizio di autorizzazione. Nell'esempio seguente, il RequireAdministratorRole criterio specifica che tutti gli utenti devono essere nel ruolo di Administrator

services.AddAuthorization(options =>
{
    options.AddPolicy("RequireAdministratorRole",
        policy => policy.RequireRole("Administrator"));
});

I criteri vengono applicati usando la proprietà Policysull'attributo [Authorize]:

[Authorize(Policy = "RequireAdministratorRole")]
public IActionResult Shutdown() { ... }

Per specificare più ruoli consentiti in un requisito, specificare i ruoli come parametri per il RequireRole metodo . Nell'esempio seguente gli utenti sono autorizzati se appartengono ai Administratorruoli , PowerUseroBackupAdministrator :

services.AddAuthorization(options =>
{
    options.AddPolicy("ElevatedRights", policy =>
        policy.RequireRole("Administrator", "PowerUser", "BackupAdministrator"));
});

Se si vuole che i criteri richiedano tutti i ruoli precedenti, concatenare i ruoli al generatore di criteri o specificarli singolarmente nel generatore di criteri in un'istruzione lambda.

Concatenato al generatore di criteri:

services.AddAuthorization(options =>
{
    options.AddPolicy("ElevatedRights", policy =>
        policy
            .RequireRole("Administrator")
            .RequireRole("PowerUser")
            .RequireRole("BackupAdministrator"));
});

In alternativa, usare un'istruzione lambda:

services.AddAuthorization(options =>
{
    options.AddPolicy("ElevatedRights",
        policy =>
        {
            policy.RequireRole("Administrator");
            policy.RequireRole("PowerUser");
            policy.RequireRole("BackupAdministrator");
        });
});

Gruppi di sicurezza dell'Autenticazione di Windows come ruoli applicativi

Dopo aver configurato l'app per l'autenticazione di Windows con i computer client e server che fanno parte dello stesso dominio di Windows, i gruppi di sicurezza utente vengono automaticamente inclusi come attestazioni nelle richieste dell'utente ClaimsPrincipal.

Il User.Identity è tipicamente un WindowsIdentity quando si usa l'autenticazione di Windows ed è possibile recuperare i reclami del gruppo SID o verificare se un utente appartiene a un ruolo con il codice seguente, dove il {DOMAIN} segnaposto è il dominio e {SID GROUP NAME} il nome del gruppo SID:

if (User.Identity is WindowsIdentity windowsIdentity)
{
    var groups = windowsIdentity.Groups;

    // If needed, obtain a list of the SID groups
    var securityGroups = 
        groups.Select(g => g.Translate(typeof(NTAccount)).ToString()).ToList();

    // If needed, obtain the user's Windows identity name
    var windowsIdentityName = windowsIdentity.Name;

    // Check if the user is in a specific SID group
    if (User.IsInRole(@"{DOMAIN}\{SID GROUP NAME}"))
    {
        // User is in the specified group
    }
    else
    {
        // User isn't in the specified group
    }
}
else
{
    // The user isn't authenticated with Windows Authentication
}

Per una dimostrazione del codice correlato che converte le richieste di gruppo SID in valori leggibili da esseri umani in un'app Blazor, vedere il componente UserClaims in Proteggere un ASP.NET Core Blazor Web App con l'autenticazione di Windows. Questo approccio nel recupero delle attestazioni di gruppo SID può essere combinato con l'aggiunta di attestazioni con un IClaimsTransformation per creare attestazioni di ruolo personalizzate quando un utente viene autenticato.

Un approccio simile all'esempio precedente per il recupero di rivendicazioni di gruppo SID può essere combinato con l'aggiunta di rivendicazioni con un IClaimsTransformation per creare rivendicazioni di ruolo personalizzate quando un utente viene autenticato.

Risorse aggiuntive