Ayant utilisé diverses techniques d'authentification et d'autorisation pendant des décennies, mon application MVC actuelle utilise la méthodologie suivante.
Les revendications sont utilisées pour toutes les autorisations. Les utilisateurs se voient attribuer un rôle (plusieurs rôles sont possibles mais je n'en ai pas besoin) - plus d'informations ci-dessous.
Comme c'est la pratique courante, une classe d'attribut ClaimsAuthorize est utilisée. Étant donné que la plupart des actions de contrôleur sont CRUD, j'ai une routine dans la génération de base de données code-first qui itère toutes les actions de contrôleur et crée des types de revendication pour chaque attribut d'action de contrôleur de Lire / Modifier / Créer / Supprimer. Par exemple de,
[ClaimsAuthorize("SomeController", "Edit")]
[HttpPost]
Pour une utilisation dans une vue MVC, une classe de contrôleur de base présente des éléments de sac de vue
protected override void OnActionExecuting(ActionExecutingContext filterContext)
{
// get user claims
var user = filterContext.HttpContext.User as System.Security.Claims.ClaimsPrincipal;
if (user != null)
{
// Get all user claims on this controller. In this controler base class, [this] still gets the descendant instance type, hence name
List<Claim> claims = user.Claims.Where(c => c.Type == this.GetType().Name).ToList();
// set Viewbag with default authorisations on this controller
ViewBag.ClaimRead = claims.Any(c => c.Value == "Read");
ViewBag.ClaimEdit = claims.Any(c => c.Value == "Edit");
ViewBag.ClaimCreate = claims.Any(c => c.Value == "Create");
ViewBag.ClaimDelete = claims.Any(c => c.Value == "Delete");
}
base.OnActionExecuting(filterContext);
}
Pour les menus du site Web et d'autres actions non liées au contrôleur, j'ai d'autres réclamations. Par exemple, si un utilisateur peut afficher un champ monétaire particulier.
bool UserHasSpecificClaim(string claimType, string claimValue)
{
// get user claims
var user = this.HttpContext.User as System.Security.Claims.ClaimsPrincipal;
if (user != null)
{
// Get the specific claim if any
return user.Claims.Any(c => c.Type == claimType && c.Value == claimValue);
}
return false;
}
public bool UserHasTradePricesReadClaim
{
get
{
return UserHasSpecificClaim("TradePrices", "Read");
}
}
Alors, où se situent les rôles?
J'ai un tableau qui lie un rôle à un ensemble (par défaut) de revendications. Lors de la définition de l'autorisation utilisateur, la valeur par défaut est de donner à l'utilisateur les revendications de son rôle. Chaque utilisateur peut avoir plus ou moins de revendications que la valeur par défaut. Pour simplifier l'édition, la liste des revendications est affichée par contrôleur et actions (dans une ligne), avec d'autres revendications ensuite répertoriées. Les boutons sont utilisés avec un peu de Javascript pour sélectionner un ensemble d'actions afin de minimiser le «clic» requis pour sélectionner les revendications. Lors de l'enregistrement, les revendications des utilisateurs sont supprimées et toutes les revendications sélectionnées sont ajoutées. L'application Web ne charge les revendications qu'une seule fois, de sorte que toute modification doit entraîner un rechargement dans ces données statiques.
Les responsables peuvent donc sélectionner quelles revendications sont dans chaque rôle et quelles revendications un utilisateur a après leur attribution à un rôle et à ces revendications par défaut. Le système ne compte qu'un petit nombre d'utilisateurs, la gestion de ces données est donc simple