Utilisez des rôles pour autoriser les utilisateurs
Les identités des utilisateurs dans .NET Core peuvent appartenir à un ou plusieurs rôles définis. Ces rôles peuvent ensuite être utilisés pour limiter les accès à différentes parties du système. Par exemple, si votre système utilise un rôle d'administrateur, vous pouvez vous servir de ce rôle pour identifier les utilisateurs disposant de privilèges d'accès de niveau administrateur. Les autres utilisateurs peuvent alors disposer de privilèges plus limités via des rôles de développeur ou de simple utilisateur.
Je comprends bien le principe, mais d'où viennent ces rôles ? Existe-t-il une liste prédéfinie ?
Non, pas du tout. C'est à vous de définir les rôles dont vous avez besoin. Vous pouvez le faire dans le système pendant le développement ou les ajouter plus tard via l'interface utilisateur. Ce que vous devez savoir, c'est comment ajouter ces rôles avec du code C#.
Tout comme il existe une classe UserManager pour gérer les utilisateurs, il existe une classe RoleManager pour gérer les rôles. La méthode d'accès est la même pour les deux : l'injection de dépendance. En injectant une instance de la classe RoleManager par l'intermédiaire d'un constructeur d'une classe de contrôleur, vous pouvez accéder à tout ce dont vous avez besoin pour créer et gérer des rôles.
Voici un exemple de code qui montre comment vérifier l'existence d'un rôle Administrateur et le créer s'il n'existe pas :
bool roleExiste = await _roleManager.RoleExistsAsync("Administrateur");
if (!roleExiste)
{
var role = new IdentityRole();
role.Name = " Administrateur ";
await _roleManager.CreateAsync(role);
}
Ensuite, pour affecter un utilisateur au rôle, transmettez une instance de la classe des données d'identité de l'utilisateur à la méthode AddToRoleAsync
de la classe UserManager :
var resultat = await _userManager.AddToRoleAsync(user, "Administrateur");
Enfin, pour limiter l'accès d'une zone du code, aux utilisateurs authentifiés, qu'il s'agisse d'une classe entière ou d'une seule méthode, utilisez l'attribut Authorize
. Nous avons appris à l'utiliser dans notre cours sur l'architecture MVC.
Pour étendre l'attribut Authorize
à des rôles, utilisez la syntaxe suivante :
[Authorize(Roles = "Administrateur")]
public class AdminController : Controller
{
}
Vous pouvez aussi combiner des rôles. Dans cet exemple, l'indication de deux rôles dans un seul attribut Authorize
spécifie qu'un utilisateur doit être membre de l'un de ces deux rôles pour pouvoir accéder à la classe :
[Authorize(Roles = "Administrateur, Developpeur")]
public class DevController : Controller
{
}
Si vous spécifiez ces mêmes rôles dans deux attributs Authorize
distincts, alors il faudra qu'un utilisateur soit membre des deux rôles pour pouvoir accéder à la classe :
[Authorize(Roles = "Administrateur")]
[Authorize(Roles = "Developpeur")]
public class AdminDevController : Controller
{
}
Utilisez les revendications et stratégies pour autoriser des utilisateurs
Les revendications se rapprochent des rôles, car elles limitent l'accès d'un utilisateur, mais elles permettent d’être encore plus précis. Si l'on comparait un rôle à un poste, ou à un niveau de prestige, une revendication serait davantage une caractéristique personnelle.
Les exemples suivants peuvent être considérés comme des autorisations basées sur des revendications dans le monde réel :
Vous devez mesurer au moins 1 m 20 pour faire ce tour de montagnes russes.
Vous devez avoir au moins 21 ans pour pouvoir entrer dans ce club.
Soirée spéciale femmes le mardi soir ! Boissons gratuites pour les femmes !
Réduction pour les seniors au cinéma.
Ces revendications sont basées sur la valeur d'un attribut ou d'une propriété qui est propre à une personne, comme son âge, sa taille ou son sexe. Si vous envisagez une application Web sous cet angle, elles permettent de réserver l'accès aux zones protégées de l'application aux seuls utilisateurs dont les revendications correspondent aux critères.
Les revendications sont basées sur des stratégies. En tant que développeur, il est de votre responsabilité de créer et d'enregistrer les stratégies présentant les critères de vos revendications.
Les revendications et leurs stratégies sont enregistrées dans la méthode ConfigureServices
du fichier Startup.cs de votre projet .NET Core. L'exemple suivant enregistre une revendication pour notre exemple de soirée spéciale femmes :
services.AddAuthorization(options =>
{
options.AddPolicy("SoireeFemmes", policy => policy.RequireClaim("Sexe",
"Femme"));
});
Si la valeur de la revendication n'est pas une valeur unique ou impose une transformation ou une comparaison (âge minimal, par exemple), vous devez utiliser un gestionnaire pour traiter la stratégie et non une simple valeur d'attribut.
L'exemple suivant illustre l'utilisation d'un gestionnaire pour valider la taille minimale nécessaire pour accéder à des montagnes russes :
services.AddAuthorization(options =>
{
options.AddPolicy("TailleMini120", policy => policy.Requirements.Add(
new TailleMinimale(120)));
});
Notez que ce critère que nous ajoutons à la stratégie est un objet dont le constructeur reçoit la valeur minimale indiquée. C'est à ce niveau que la revendication et la stratégie nécessitent un peu plus de travail.
Tout d'abord, vous devez créer une classe TailleMinimale
:
using Microsoft.AspNetCore.Authorization;
public class TailleMinimale : IAuthorizationRequirement
{
public int TailleMin { get; }
public TailleMinimale(int tailleMin)
{
TailleMin = tailleMin;
}
}
Ensuite, créez la classe de gestionnaire pour la taille minimale :
using System;
using System.Security.Claims;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Authorization;
using PoliciesAuthApp1.Services.Requirements;
public class GestionnaireTailleMinimale : AuthorizationHandler<TailleMinimale>
{
protected override Task HandleRequirementAsync(AuthorizationHandlerContext
context, TailleMinimale critere)
{
var taille = context.User.FindFirst(c => c.Type == TypesRequete.Taille).Value);
if (taille >= critere.TailleMin)
{
context.Succeed(critere);
}
return Task.CompletedTask;
}
}
Maintenant que le code de votre gestionnaire est écrit, enregistrez ce dernier dans la méthode ConfigureServices
. Ajoutez une ligne de code sous la ligne de la stratégie :
public void ConfigureServices(IServiceCollection services)
{
...
services.AddAuthorization(options =>
{
options.AddPolicy("TailleMini120", policy => policy.Requirements.Add(
new TailleMinimale(120)));
});
services.AddSingleton<IAuthorizationHandler, GestionnaireTailleMinimale>();
}
Utilisez la nouvelle stratégie
Vous pouvez maintenant utiliser la stratégie pour que votre revendication interdise ou accorde l'accès à une partie du code. Procédez comme nous l'avons vu précédemment avec les rôles. Pour limiter l'accès à toute une classe sur la base d'une taille minimale, utilisez la syntaxe suivante :
[Authorize(Policy = "TailleMinimale120")]
public class MontagnesRussesController : Controller
{
public IActionResult Index() => View();
}
En résumé
Dans ce chapitre, vous avez découvert comment contrôler l'accès aux pages et données d'une application à l'aide de méthodes de sécurité basées sur les rôles et les stratégies. Concrètement, vous avez appris comment :
utiliser l'attribut
Authorize
avec des noms de rôle pour autoriser l'accès en fonction de l'appartenance d'un utilisateur à un rôle donné ;utiliser des revendications pour créer des stratégies basées sur ces revendications ;
utiliser l'attribut
Authorize
avec des stratégies pour bénéficier d'un contrôle d'accès plus précis.
Il est désormais temps d'évaluer ce que vous avez appris dans la deuxième partie de ce cours en répondant au quiz !