Autorisation basée sur les rôles dans ASP.NET Core

Lorsqu’une identité est créée, elle peut appartenir à un ou plusieurs rôles. Par exemple, Tracy peut appartenir aux rôles Administrator et User tandis que Scott peut uniquement appartenir au rôle User. La façon dont ces rôles sont créés et gérés dépend du magasin de stockage du processus d’autorisation. Les rôles sont exposés au développeur via la méthode IsInRole sur la classe ClaimsPrincipal. AddRoles doit être ajouté aux services de rôle.

Bien que les rôles soient des revendications, toutes les revendications ne sont pas des rôles. Selon l’émetteur d’identité, un rôle peut être une collection d’utilisateurs qui peuvent appliquer des revendications pour les membres du groupe, ainsi qu’une revendication réelle sur une identité. Toutefois, les revendications sont destinées à être des informations sur un utilisateur individuel. L’utilisation de rôles pour ajouter des revendications à un utilisateur peut confondre la limite entre l’utilisateur et ses revendications individuelles. Cette confusion est la raison pour laquelle les modèles SPA ne sont pas conçus autour des rôles. En outre, pour les organisations qui migrent à partir d’un système hérité local, la prolifération des rôles au fil des ans peut signifier qu’une revendication de rôle peut être trop volumineuse pour être contenue dans un jeton utilisable par les SPAs. Pour sécuriser les applications monopage, consultez Utiliser Identity pour sécuriser un back-end d’API web pour les applications monopage.

Ajouter des services de rôle à Identity

Inscrivez les services d’autorisation basés sur les rôles dans Program.cs en appelant AddRoles avec le type de rôle dans la configuration de l’application Identity. Le type de rôle dans l’exemple suivant est IdentityRole :

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

Ajout de vérifications de rôle

Vérifications d’autorisation basées sur les rôles :

  • Sont déclaratifs et spécifient des rôles dont l’utilisateur actuel doit être membre pour accéder à la ressource demandée.
  • Sont appliqués aux Pages Razor, aux contrôleurs ou aux actions au sein d’un contrôleur.
  • Ne peuvent pas être appliqués au niveau du Razor gestionnaire de pages, ils doivent être appliqués à la page.

Par exemple, le code suivant limite l’accès à toutes les actions sur le AdministrationController aux utilisateurs qui sont membres du rôle Administrator :

[Authorize(Roles = "Administrator")]
public class AdministrationController : Controller
{
    public IActionResult Index() =>
        Content("Administrator");
}

Plusieurs rôles peuvent être spécifiés sous la forme d’une liste séparée par des virgules :

[Authorize(Roles = "HRManager,Finance")]
public class SalaryController : Controller
{
    public IActionResult Payslip() =>
                    Content("HRManager || Finance");
}

Le SalaryController est accessible uniquement aux utilisateurs qui sont membres du HRManager rôle ou du rôleFinance.

Lorsque plusieurs attributs sont appliqués, un utilisateur accédant doit être membre de tous les rôles spécifiés. L’exemple suivant nécessite qu’un utilisateur soit membre à la foisdu rôlePowerUseretControlPanelUser :

[Authorize(Roles = "PowerUser")]
[Authorize(Roles = "ControlPanelUser")]
public class ControlPanelController : Controller
{
    public IActionResult Index() =>
        Content("PowerUser && ControlPanelUser");
}

L’accès à une action peut être limité en appliquant des attributs d’autorisation de rôle supplémentaires au niveau de l’action :

[Authorize(Roles = "Administrator, PowerUser")]
public class ControlAllPanelController : Controller
{
    public IActionResult SetTime() =>
        Content("Administrator || PowerUser");

    [Authorize(Roles = "Administrator")]
    public IActionResult ShutDown() =>
        Content("Administrator only");
}

Dans le contrôleur précédent ControlAllPanelController :

  • Les membres du rôle Administratorou du rôle PowerUser peuvent accéder au contrôleur et à l’action SetTime.
  • Seuls les membres du rôle Administrator peuvent accéder à l'action ShutDown.

Un contrôleur peut être verrouillé, mais autoriser l’accès anonyme et non authentifié à des actions individuelles :

[Authorize]
public class Control3PanelController : Controller
{
    public IActionResult SetTime() =>
        Content("[Authorize]");

    [AllowAnonymous]
    public IActionResult Login() =>
        Content("[AllowAnonymous]");
}

Pour Razor Pages, [Authorize] peut être appliqué par :

[Authorize(Policy = "RequireAdministratorRole")]
public class UpdateModel : PageModel
{
    public IActionResult OnPost() =>
         Content("OnPost RequireAdministratorRole");
}

Important

Les attributs de filtre, y compris AuthorizeAttribute, ne peuvent être appliqués qu’à PageModel et ne peuvent pas être appliqués à des méthodes de gestionnaire de pages spécifiques.

Vérifications des rôles basés sur des stratégies

Les exigences de rôle peuvent également être exprimées à l’aide de la syntaxe de stratégie, où un développeur inscrit une stratégie au démarrage de l’application dans le cadre de la configuration du service d’autorisation. Cela se produit généralement dans le fichier Program.cs :

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddRazorPages();
builder.Services.AddControllersWithViews();

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

var app = builder.Build();

if (!app.Environment.IsDevelopment())
{
    app.UseExceptionHandler("/Error");
    app.UseHsts();
}

app.UseHttpsRedirection();
app.UseStaticFiles();

app.UseAuthentication();
app.UseAuthorization();

app.MapDefaultControllerRoute();
app.MapRazorPages();

app.Run();

Les stratégies sont appliquées à l’aide de la propriété Policy sur l’attribut [Authorize] :

[Authorize(Policy = "RequireAdministratorRole")]
public IActionResult Shutdown()
{
    return View();
}

Pour spécifier plusieurs rôles autorisés dans une exigence, spécifiez-les en tant que paramètres de la méthodeRequireRole :

var builder = WebApplication.CreateBuilder(args);

builder.Services.AddRazorPages();
builder.Services.AddControllersWithViews();

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

var app = builder.Build();

Le code précédent autorise les utilisateurs qui appartiennent aux rôles Administrator, PowerUser ou BackupAdministrator.

Lorsqu’une identité est créée, elle peut appartenir à un ou plusieurs rôles. Par exemple, Tracy peut appartenir aux rôles Administrateur et Utilisateur, tandis que Scott ne peut appartenir qu’au rôle Utilisateur. La façon dont ces rôles sont créés et gérés dépend du magasin de stockage du processus d’autorisation. Les rôles sont exposés au développeur via la méthode IsInRole sur la classe ClaimsPrincipal.

Nous vous recommandons de ne pas utiliser des rôles en tant que revendications, mais plutôt d’utiliser des revendications. Lors de l’utilisation d’applications monopage (SPA), consultez Utiliser Identity pour sécuriser un back-end d’API web pour les applications monopage.

Ajout de vérifications de rôle

Vérifications d’autorisation basées sur les rôles :

  • Sont déclaratifs.
  • Sont appliqués aux Pages Razor, aux contrôleurs ou aux actions au sein d’un contrôleur.
  • Ne peuvent pas être appliqués au niveau du Razor gestionnaire de pages, ils doivent être appliqués à la page.

Les vérifications d’autorisation basées sur les rôles spécifient les rôles dont l’utilisateur actuel doit être membre pour accéder à la ressource demandée.

Par exemple, le code suivant limite l’accès à toutes les actions sur le AdministrationController aux utilisateurs qui sont membres du rôle Administrator :

[Authorize(Roles = "Administrator")]
public class AdministrationController : Controller
{
    public IActionResult Index() =>
        Content("Administrator");
}

Plusieurs rôles peuvent être spécifiés sous la forme d’une liste séparée par des virgules :

[Authorize(Roles = "HRManager,Finance")]
public class SalaryController : Controller
{
    public IActionResult Payslip() =>
                    Content("HRManager || Finance");
}

Le SalaryController est accessible uniquement aux utilisateurs qui sont membres du HRManager rôle ou du rôleFinance.

Si vous appliquez plusieurs attributs, un utilisateur accédant doit être membre de tous les rôles spécifiés. L’exemple suivant nécessite qu’un utilisateur soit membre à la fois du rôle PowerUser et ControlPanelUser :

[Authorize(Roles = "PowerUser")]
[Authorize(Roles = "ControlPanelUser")]
public class ControlPanelController : Controller
{
    public IActionResult Index() =>
        Content("PowerUser && ControlPanelUser");
}

Vous pouvez limiter davantage l’accès en appliquant des attributs d’autorisation de rôle supplémentaires au niveau de l’action :

[Authorize(Roles = "Administrator, PowerUser")]
public class ControlAllPanelController : Controller
{
    public IActionResult SetTime() =>
        Content("Administrator || PowerUser");

    [Authorize(Roles = "Administrator")]
    public IActionResult ShutDown() =>
        Content("Administrator only");
}

Si plusieurs attributs sont appliqués au niveau du contrôleur et de l’action, tous les attributs doivent passer avant que l’accès soit accordé :

[Authorize(Roles = "Administrator")]
public class ControlAllPanelController2 : Controller
{
    public IActionResult SetTime() =>
        Content("Administrator only");

    [Authorize(Roles = "PowerUser")]
    public IActionResult ShutDown() =>
        Content("Administrator && PowerUser");
}

Dans le contrôleur précédent ControlAllPanelController :

  • Les membres du rôle Administratorou du rôle PowerUser peuvent accéder au contrôleur et à l’action SetTime.
  • Seuls les membres du rôle Administrator peuvent accéder à l'action ShutDown.

Vous pouvez également verrouiller un contrôleur, mais autoriser l’accès anonyme et non authentifié à des actions individuelles.

[Authorize]
public class Control3PanelController : Controller
{
    public IActionResult SetTime() =>
        Content("[Authorize]");

    [AllowAnonymous]
    public IActionResult Login() =>
        Content("[AllowAnonymous]");
}

Pour Razor Pages, le [Authorize] peut être appliqué par :

[Authorize(Policy = "RequireAdministratorRole")]
public class UpdateModel : PageModel
{
    public ActionResult OnPost()
    {
    }
}

Important

Les attributs de filtre, y compris AuthorizeAttribute, ne peuvent être appliqués qu’à PageModel et ne peuvent pas être appliqués à des méthodes de gestionnaire de pages spécifiques.

Vérifications des rôles basés sur des stratégies

Les exigences de rôle peuvent également être exprimées à l’aide de la nouvelle syntaxe de stratégie, où un développeur inscrit une stratégie au démarrage dans le cadre de la configuration du service d’autorisation. Cela se produit normalement dans ConfigureServices() dans votre fichier Startup.cs.

public void ConfigureServices(IServiceCollection services)
{
    services.AddControllersWithViews();
    services.AddRazorPages();

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

Les stratégies sont appliquées à l’aide de la propriété Policy sur l’attribut [Authorize] :

[Authorize(Policy = "RequireAdministratorRole")]
public IActionResult Shutdown()
{
    return View();
}

Si vous souhaitez spécifier plusieurs rôles autorisés dans une exigence, vous pouvez les spécifier en tant que paramètres de la méthode RequireRole :

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

Cet exemple autorise les utilisateurs qui appartiennent aux Administratorrôles, PowerUser ou BackupAdministrator.

Ajouter des services de rôle à Identity

Ajoutez AddRoles pour ajouter des services de rôle :

public void ConfigureServices(IServiceCollection services)
{
    services.AddDbContext<ApplicationDbContext>(options =>
        options.UseSqlServer(
            Configuration.GetConnectionString("DefaultConnection")));
    services.AddDefaultIdentity<IdentityUser>()
        .AddRoles<IdentityRole>()
        .AddEntityFrameworkStores<ApplicationDbContext>();

    services.AddControllersWithViews();
    services.AddRazorPages();
}