Avez-vous déjà essayé dans l'un de vos projets ASP.NET MVC d'utiliser un attribut [Authorize] pour par exemple assigner des rôles, en utilisant la valeur d'une Enum ?
Si c'est le cas, vous obtiendrez le message d'erreur suivant en anglais lors de la compilation :
An attribute argument must be a constant expression, typeof expression or array creation expression of an attribute parameter type
C'est parce que vous avez besoin d'utiliser des valeurs statiques et il est impossible d'utiliser une Enum pour définir les propriétés d'un Attribute. Cela signifie que vous ne pouvez pas définir la propriété Roles d'un [AuthorizeAttribute] avec une valeur d'Enum.
C'est frustrant, parce que personnellement je n'aime pas avoir à coder en dur les rôles dans une application. Cela rend l'application pas très lisible et plus compliquée à maintenir.
Heureusement, ASP.NET MVC nous permet de personnaliser l'[AuthorizeAttribute] facilement sans avoir à remplacer le processus de sécurité standard.
Création
Pour nos besoins, nous allons créer l'Enum ci-dessous pour déclarer les rôles:
namespace MvcApplication.HowTo.Enums { public enum Role { Administrator = 1, UserWithPrivileges = 2, User = 3, } }
Maintenant, nous allons créer un [AuthorizeAttribute] personnalisé qui accepte des Enum en tant que paramètres dans le constructeur. Il héritera de System.Web.Mvc.AuthorizeAttribute :
using System; using System.Linq; using System.Web.Mvc; namespace MvcApplication.HowTo.Attributes { [AttributeUsage(AttributeTargets.Method | AttributeTargets.Class, Inherited = true, AllowMultiple = true)] public class AuthorizeEnumAttribute : AuthorizeAttribute { public AuthorizeEnumAttribute(params object[] roles) { if (roles.Any(r => r.GetType().BaseType != typeof(Enum))) throw new ArgumentException("roles"); this.Roles = string.Join(",", roles.Select(r => Enum.GetName(r.GetType(), r))); } } }
Comme vous pouvez le voir, il faut prêter attention à plusieurs choses ici :
Exemple d'utilisation
using System.Web.Mvc; using MvcApplication.HowTo.Attributes; using MvcApplication.HowTo.Enums; namespace MvcApplication.HowTo.Controllers { public class HomeController : Controller { public ActionResult Index() { ViewBag.Message = "Welcome to ASP.NET MVC!"; return View(); } public ActionResult About() { return View(); } [AuthorizeEnum(Role.Administrator, Role.UserWithPrivileges)] public ActionResult ThePrivilegeZone() { return View(); } } }
Notre code est propre comme ça, n'est-ce pas ?
Pour aller plus loin
Si l'on regarde avec un outil comme Reflector, il est intéressant de comprendre comment l'action ThePrivilegeZone est décorée lors de la compilation. Voici une capture d'écran :
Nous comprenons qu'une fois compilées, les valeurs de l'Enum Role sont utilisés et non les noms. Ici 1 (Administrator) et 2 (UserWithPrivileges).
Notez que si vous utilisez une Enum pour vos rôles sans mettre de valeurs comme nous l'avons fait ici, les valeurs de l'Enum seront dans l'ordre 0, 1, 2, etc juqsu'au nombre de vos rôles moins 1.
En résumé
Nous avons vu comment créer et utiliser un AuthorizeAttribute personnalisé qui accepte des paramètres de type enum. Ici nous définissons seulement la propriété Roles, mais en fonction de vos besoins vous pouvez faire la même chose avec la propriété Users. Personnellement, j'utilise cet attribut personnalisé dans mon framework afin de le réutiliser dans tous mes projets ASP.NET MVC.
Vous pouvez télécharger la solution exemple ici :
Download the Authorize Enum Solution
(Notez que le projet utilise ASP.NET MVC 3)
N'hésitez pas à commenter ou à me contacter si vous avez des questions à propos de cet article.
Thats Great!
Is it possible to use a [Flags] Enum ?
This is exactly where I was looking for, thanks a lot!
hi
thank you for this article
how to save roles in database,and dynamic parameter Authorize?
thanks
Good Information.
Also exactly what I was looking for too! Thanks!
this is the ONLY place on the entire web that talks about passing parms.
Can you please expand this to show the MVC web page - so that we can dynamically assign the roles http://bit.ly/2iyt146