asp.net mvc decorate con múltiples enumeraciones

Tengo un controlador y quiero que dos roles puedan acceder a él. 1-administrador O 2-moderador

Sé que puedes hacer [Authorize (Roles = “admin, moderators”)] pero tengo mis roles en una enumeración. Con la enumeración, solo puedo autorizar UNA función. No puedo entender cómo autorizar dos.

He intentado algo como [Authorize (Roles = MyEnum.Admin, MyEnum.Moderator)] pero eso no comstackrá.

Alguien una vez sugirió esto:

[Authorize(Roles=MyEnum.Admin)] [Authorize(MyEnum.Moderator)] public ActionResult myAction() { } 

pero no funciona como un quirófano. Creo que en este caso el usuario debe ser parte de AMBOS roles. ¿Estoy pasando por alto alguna syntax? ¿O es este un caso en el que tengo que rodar mi propia autorización personalizada?

Intente usar el operador O de bit como este:

 [Authorize(Roles= MyEnum.Admin | MyEnum.Moderator)] public ActionResult myAction() { } 

Si eso no funciona, puedes hacer tu propio. Actualmente solo hice esto en mi proyecto. Esto es lo que hice:

 public class AuthWhereRole : AuthorizeAttribute { ///  /// Add the allowed roles to this property. ///  public UserRole Is; ///  /// Checks to see if the user is authenticated and has the /// correct role to access a particular view. ///  ///  ///  protected override bool AuthorizeCore(HttpContextBase httpContext) { if (httpContext == null) throw new ArgumentNullException("httpContext"); // Make sure the user is authenticated. if (!httpContext.User.Identity.IsAuthenticated) return false; UserRole role = someUser.Role; // Load the user's role here // Perform a bitwise operation to see if the user's role // is in the passed in role values. if (Is != 0 && ((Is & role) != role)) return false; return true; } } // Example Use [AuthWhereRole(Is=MyEnum.Admin|MyEnum.Newbie)] public ActionResult Test() {} 

Además, asegúrese de agregar un atributo de indicadores a su enumeración y asegúrese de que estén todos valorados desde 1 en adelante. Me gusta esto:

 [Flags] public enum Roles { Admin = 1, Moderator = 1 << 1, Newbie = 1 << 2 etc... } 

El desplazamiento del bit izquierdo da los valores 1, 2, 4, 8, 16 y así sucesivamente.

Bueno, espero que esto ayude un poco.

Aquí hay una solución simple y elegante que le permite simplemente usar la siguiente syntax:

 [AuthorizeRoles(MyEnum.Admin, MyEnum.Moderator)] 

Al crear su propio atributo, use la palabra clave params en su constructor:

 public class AuthorizeRoles : AuthorizeAttribute { public AuthorizeRoles(params MyEnum[] roles) { ... } protected override bool AuthorizeCore(HttpContextBase httpContext) { ... } } 

Esto le permitirá usar el atributo de la siguiente manera:

 [AuthorizeRoles(MyEnum.Admin, MyEnum.Moderator)] public ActionResult myAction() { } 

Combiné algunas de las soluciones aquí para crear mi favorito personal. Mi atributo personalizado simplemente cambia los datos para que estén en el formato que espera SimpleMembership y le permite manejar todo lo demás.

Mis roles enum:

 public enum MyRoles { Admin, User, } 

Para crear roles:

 public static void CreateDefaultRoles() { foreach (var role in Enum.GetNames(typeof(MyRoles))) { if (!Roles.RoleExists(role)) { Roles.CreateRole(role); } } } 

Atributo personalizado:

 public class AuthorizeRolesAttribute : AuthorizeAttribute { public AuthorizeRolesAttribute(params MyRoles[] allowedRoles) { var allowedRolesAsStrings = allowedRoles.Select(x => Enum.GetName(typeof(MyRoles), x)); Roles = string.Join(",", allowedRolesAsStrings); } } 

Usado así:

 [AuthorizeRoles(MyRoles.Admin, MyRoles.User)] public ActionResult MyAction() { return View(); } 

Tratar

 public class CustomAuthorize : AuthorizeAttribute { public enum Role { DomainName_My_Group_Name, DomainName_My_Other_Group_Name } public CustomAuthorize(params Role[] DomainRoles) { foreach (var domainRole in DomainRoles) { var domain = domainRole.ToString().Split('_')[0] + "_"; var role = domainRole.ToString().Replace(domain, "").Replace("_", " "); domain=domain.Replace("_", "\\"); Roles += ", " + domain + role; } Roles = Roles.Substring(2); } } public class HomeController : Controller { [CustomAuthorize(Role.DomainName_My_Group_Name, Role.DomainName_My_Other_Group_Name)] public ActionResult Index() { return View(); } } 

Aquí está mi versión, basada en las respuestas de @CalebHC y @Lee Harold.

Seguí el estilo de usar parámetros con nombre en el atributo y anulé la propiedad Roles clases base.

La respuesta de @CalebHC utiliza una nueva propiedad Is que creo que es innecesaria, porque se reemplaza a AuthorizeCore() (que en la clase base usa roles) por lo que tiene sentido usar nuestros propios Roles también. Al usar nuestros propios Roles , escribimos Roles = Roles.Admin en el controlador, que sigue el estilo de otros atributos .Net.

Utilicé dos constructores en CustomAuthorizeAttribute para mostrar los nombres de los grupos de directorios activos que se pasaron. En producción utilizo el constructor parametrizado para evitar cadenas mágicas en la clase: los nombres de los grupos se extraen de web.config durante Application_Start() y se pasan a creación usando una herramienta DI.

Necesitará un NotAuthorized.cshtml o similar en su carpeta Views\Shared o los usuarios no autorizados obtendrán una pantalla de error.

Aquí está el código para la clase base AuthorizationAttribute.cs .

Controlador:

 public ActionResult Index() { return this.View(); } [CustomAuthorize(Roles = Roles.Admin)] public ActionResult About() { return this.View(); } 

CustomAuthorizeAttribute:

 // The left bit shifting gives the values 1, 2, 4, 8, 16 and so on. [Flags] public enum Roles { Admin = 1, User = 1 << 1 } [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, Inherited = true, AllowMultiple = true)] public class CustomAuthorizeAttribute : AuthorizeAttribute { private readonly string adminGroupName; private readonly string userGroupName; public CustomAuthorizeAttribute() : this("Domain Admins", "Domain Users") { } private CustomAuthorizeAttribute(string adminGroupName, string userGroupName) { this.adminGroupName = adminGroupName; this.userGroupName = userGroupName; } ///  /// Gets or sets the allowed roles. ///  public new Roles Roles { get; set; } ///  /// Checks to see if the user is authenticated and has the /// correct role to access a particular view. ///  /// The HTTP context. /// [True] if the user is authenticated and has the correct role ///  /// This method must be thread-safe since it is called by the thread-safe OnCacheAuthorization() method. ///  protected override bool AuthorizeCore(HttpContextBase httpContext) { if (httpContext == null) { throw new ArgumentNullException("httpContext"); } if (!httpContext.User.Identity.IsAuthenticated) { return false; } var usersRoles = this.GetUsersRoles(httpContext.User); return this.Roles == 0 || usersRoles.Any(role => (this.Roles & role) == role); } protected override void HandleUnauthorizedRequest(AuthorizationContext filterContext) { if (filterContext == null) { throw new ArgumentNullException("filterContext"); } filterContext.Result = new ViewResult { ViewName = "NotAuthorized" }; } private IEnumerable GetUsersRoles(IPrincipal principal) { var roles = new List(); if (principal.IsInRole(this.adminGroupName)) { roles.Add(Roles.Admin); } if (principal.IsInRole(this.userGroupName)) { roles.Add(Roles.User); } return roles; } } 

Para agregar al código de CalebHC y responder la pregunta de ssmith sobre el manejo de usuarios que tienen múltiples roles …

Nuestro principal de seguridad personalizado devuelve una matriz de cadenas que representa todos los grupos / roles en los que se encuentra un usuario. Por lo tanto, primero debemos convertir todas las cadenas de la matriz que coinciden con los elementos de la enumeración. Finalmente, buscamos cualquier coincidencia, si es así, entonces el usuario está autorizado.

Tenga en cuenta que también estamos redirigiendo a un usuario no autorizado a una vista personalizada “No autorizada”.

Toda la clase se ve así:

 [AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, Inherited = true, AllowMultiple = true)] public class CustomAuthorizeAttribute : AuthorizeAttribute { ///  /// Add the allowed roles to this property. ///  public Roles Is { get; set; } ///  /// Checks to see if the user is authenticated and has the /// correct role to access a particular view. ///  ///  ///  protected override bool AuthorizeCore(HttpContextBase httpContext) { if (httpContext == null) throw new ArgumentNullException("httpContext"); if (!httpContext.User.Identity.IsAuthenticated) return false; var iCustomPrincipal = (ICustomPrincipal) httpContext.User; var roles = iCustomPrincipal.CustomIdentity .GetGroups() .Select(s => Enum.Parse(typeof (Roles), s)) .ToArray(); if (Is != 0 && !roles.Cast().Any(role => ((Is & role) == role))) { return false; } return true; } protected override void HandleUnauthorizedRequest(AuthorizationContext filterContext) { if (filterContext == null) throw new ArgumentNullException("filterContext"); filterContext.Result = new ViewResult { ViewName = "NotAuthorized" }; } } 

O podrías concatenar como:

[Autorizar (Roles = Common.Lookup.Item.SecurityRole.Administrator + “,” + Common.Lookup.Item.SecurityRole.Intake)]