2009-03-31 16 views
176

Ahora mismo decorar un método como este para permitir que los "miembros" para acceder a mi acción del controladorPermitir múltiples roles para acceder a la acción del controlador

[Authorize(Roles="members")] 

¿Cómo puedo permitir más de una función? Por ejemplo, el siguiente no funciona pero muestra lo que estoy tratando de hacer (permitir que los "miembros" y el acceso "admin"):

[Authorize(Roles="members", "admin")] 
+4

Por favor, cambie la respuesta aceptada para esta pregunta. La persona con la respuesta actualmente aceptada lo editó indicando que estaba equivocado. –

Respuesta

467

Otra opción es utilizar un solo filtro autorización, según las informados pero quitar las citas internas.

[Authorize(Roles="members, admin")] 
+3

Funciona en MVC3 y MVC4 +1 –

+4

También funciona en MVC 5. +1 – gkon

+4

Funciona en ASP.NET Core 1.0 (MVC 6) y Microsoft.AspNet.Identity v3. * – Soren

91

Si desea utilizar las funciones personalizadas, usted puede hacer esto:

CustomRoles clase:

public static class CustomRoles 
{ 
    public const string Administrator = "Administrador"; 
    public const string User = "Usuario"; 
} 

Uso

[Authorize(Roles = CustomRoles.Administrator +","+ CustomRoles.User)] 

Si tiene pocos papeles, tal vez sea posible Combínelos (para mayor claridad) como este:

public static class CustomRoles 
{ 
    public const string Administrator = "Administrador"; 
    public const string User = "Usuario"; 
    public const string AdministratorOrUser = Administrator + "," + User; 
} 

Uso

[Authorize(Roles = CustomRoles.AdministratorOrUser)] 
+5

Esta sería una buena respuesta, si le explicaste a las personas que no sabían qué hay detrás de CustomRoles. –

+1

@JamesSkemp bien, he extendido mi respuesta. Es muy simple. CustumRoles es una clase que he creado que contiene algunas constantes, que se corresponde con mis roles de aplicación. Lo hice por varias razones: 1) Permite el uso de intellisense para evitar errores de ortografía 2) Para simplificar el mantenimiento. Si un cambio de rol, tengo que actualizar solo un lugar dentro de mi aplicación. –

+0

@Pabloker Alternativamente, puede crear una enumeración con un atributo de Flags, p. Convert.ToString (CustomRoles.Administrator | CustomRoles.User); - Parte molesta es que esto requiere una conversión explícita – cstruter

14

Para MVC4, utilizando un Enum (UserRoles) con mis papeles, utilizo una costumbre AuthorizeAttribute.

En mi acción controlada, lo hago:

[CustomAuthorize(UserRoles.Admin, UserRoles.User)] 
public ActionResult ChangePassword() 
{ 
    return View(); 
} 

Y utilizo una costumbre AuthorizeAttribute así:

[AttributeUsage(AttributeTargets.Method | AttributeTargets.Class, Inherited = true, AllowMultiple = true)] 
public class CustomAuthorize : AuthorizeAttribute 
{ 
    private string[] UserProfilesRequired { get; set; } 

    public CustomAuthorize(params object[] userProfilesRequired) 
    { 
     if (userProfilesRequired.Any(p => p.GetType().BaseType != typeof(Enum))) 
      throw new ArgumentException("userProfilesRequired"); 

     this.UserProfilesRequired = userProfilesRequired.Select(p => Enum.GetName(p.GetType(), p)).ToArray(); 
    } 

    public override void OnAuthorization(AuthorizationContext context) 
    { 
     bool authorized = false; 

     foreach (var role in this.UserProfilesRequired) 
      if (HttpContext.Current.User.IsInRole(role)) 
      { 
       authorized = true; 
       break; 
      } 

     if (!authorized) 
     { 
      var url = new UrlHelper(context.RequestContext); 
      var logonUrl = url.Action("Http", "Error", new { Id = 401, Area = "" }); 
      context.Result = new RedirectResult(logonUrl); 

      return; 
     } 
    } 
} 

Esto es parte de FNHMVC modifed de Fabricio Martínez Tamayo https://github.com/fabriciomrtnz/FNHMVC/

+1

Su método OnAuthorization requerirá que el usuario tenga ** todos ** los roles enumerados; fue eso intencional, o te estás perdiendo un descanso en ese circuito? –

+0

@Tieson: lo inspeccioné muy de cerca, definitivamente parece que se requeriría un descanso en ese ciclo. – OcelotXL

+0

@TiesonT. y @ madrush, aprecio tu solución, realmente podría tener un descanso dentro del circuito. Cambiaré el código de arriba. –

57

Una posible simplificación sería la subclase AuthorizeAttribute:

public class RolesAttribute : AuthorizeAttribute 
{ 
    public RolesAttribute(params string[] roles) 
    { 
     Roles = String.Join(",", roles); 
    } 
} 

Uso:

[Roles("members", "admin")] 

vista semántico que es la misma que la respuesta de Jim Schmehil.

+1

Esto no funcionó, el usuario que inició sesión pudo omitir el atributo incluso si el usuario no tenía ninguno de los roles. – Urielzen

+2

Esta respuesta es mejor para cuando usa constantes como sus valores: ej. [Roles (Constants.Admin, Constants.Owner)] – user1191559

0

código Mejor con la adición de una subclase AuthorizeRole.cs

[AttributeUsage(AttributeTargets.Method | AttributeTargets.Class, Inherited = true, AllowMultiple = true)] 
    class AuthorizeRoleAttribute : AuthorizeAttribute 
    { 
     public AuthorizeRoleAttribute(params Rolenames[] roles) 
     { 
      this.Roles = string.Join(",", roles.Select(r => Enum.GetName(r.GetType(), r))); 
     } 
     protected override void HandleUnauthorizedRequest(System.Web.Mvc.AuthorizationContext filterContext) 
     { 
      if (filterContext.HttpContext.Request.IsAuthenticated) 
      { 
       filterContext.Result = new RedirectToRouteResult(
       new RouteValueDictionary { 
        { "action", "Unauthorized" }, 
        { "controller", "Home" }, 
        { "area", "" } 
        } 
      ); 
       //base.HandleUnauthorizedRequest(filterContext); 
      } 
      else 
      { 
       filterContext.Result = new RedirectToRouteResult(
       new RouteValueDictionary { 
        { "action", "Login" }, 
        { "controller", "Account" }, 
        { "area", "" }, 
        { "returnUrl", HttpContext.Current.Request.Url } 
        } 
      ); 
      } 
     } 
    } 

Cómo utilizar este

[AuthorizeRole(Rolenames.Admin,Rolenames.Member)] 

public ActionResult Index() 
{ 
return View(); 
} 
1

Otra solución clara, se puede usar constantes para mantener la convención y añadir múltiples [Autorizar] atributos.Mira esto:

public static class RolesConvention 
{ 
    public const string Administrator = "Administrator"; 
    public const string Guest = "Guest"; 
} 

Luego, en el controlador:

[Authorize(Roles = RolesConvention.Administrator)] 
[Authorize(Roles = RolesConvention.Guest)] 
[Produces("application/json")] 
[Route("api/[controller]")] 
public class MyController : Controller 
+6

Múltiples atributos 'Authorize' emplean semánticas AND y requieren que TODAS las condiciones se cumplan (es decir, el usuario tiene que estar en los roles de Administrador e Invitado). – trousyt

0

Si usted se encuentra la aplicación de esos 2 papeles a menudo se puede envolver en su propio Autorizar. Esto es realmente una extensión de la respuesta aceptada.

using System.Web.Mvc; 

public class AuthorizeAdminOrMember : AuthorizeAttribute 
{ 
    public AuthorizeAdminOrMember() 
    { 
     Roles = "members, admin"; 
    } 
} 

Y luego, aplique su nueva autorización a la Acción. Creo que esto se ve más limpio y se lee fácilmente.

public class MyController : Controller 
{ 
    [AuthorizeAdminOrMember] 
    public ActionResult MyAction() 
    { 
     return null; 
    } 
} 
Cuestiones relacionadas