net mvc multiple form buttons asp asp.net-mvc authorization roles

asp.net-mvc - multiple - button submit action mvc



asp.net mvc decorate[Authorize()] con mĂșltiples enumeraciones (7)

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

He seguido el estilo de uso de parámetros con nombre en el atributo y he anulado la propiedad de Roles clases base.

La respuesta de @ CalebHC usa una nueva propiedad Is que creo que no es necesaria, porque AuthorizeCore() está anulada (que en la clase base usa roles), por lo que también tiene sentido usar nuestros propios Roles . Al usar nuestros propios Roles podemos escribir Roles = Roles.Admin en el controlador, que sigue el estilo de otros atributos .Net.

He usado dos constructores para CustomAuthorizeAttribute para mostrar los nombres reales de los grupos del directorio activo que se están pasando. En producción, uso 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 Creación utilizando 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; } /// <summary> /// Gets or sets the allowed roles. /// </summary> public new Roles Roles { get; set; } /// <summary> /// Checks to see if the user is authenticated and has the /// correct role to access a particular view. /// </summary> /// <param name="httpContext">The HTTP context.</param> /// <returns>[True] if the user is authenticated and has the correct role</returns> /// <remarks> /// This method must be thread-safe since it is called by the thread-safe OnCacheAuthorization() method. /// </remarks> 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<Roles> GetUsersRoles(IPrincipal principal) { var roles = new List<Roles>(); if (principal.IsInRole(this.adminGroupName)) { roles.Add(Roles.Admin); } if (principal.IsInRole(this.userGroupName)) { roles.Add(Roles.User); } return roles; } }

Tengo un controlador y quiero dos roles para poder acceder a él. 1-admin O 2-moderador

Sé que puedes hacer [Autorizar (Roles = "admin, moderadores")] pero tengo mis roles en una enumeración. Con la enumeración solo puedo autorizar UN rol. No puedo averiguar cómo autorizar dos.

He intentado algo como [Autorizar (Roles = MyEnum.Admin, MyEnum.Moderator)] pero eso no se compila.

Alguien una vez sugirió esto:

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

pero no funciona como un OR. Creo que en este caso el usuario tiene que ser parte de AMBOS roles. ¿Estoy pasando por alto alguna sintaxis? ¿O es este un caso en el que tengo que pasar mi propia autorización personalizada?


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

[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á utilizar 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 solo cambia los datos para que estén en la forma que SimpleMembership espera y le permite manejar todo lo demás.

Enumero mis roles:

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); } }

Utilizado como tal:

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


Intente usar el operador de bit OR así:

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

Si eso no funciona, podrías rodar el tuyo. Actualmente acabo de hacer esto en mi proyecto. Esto es lo que hice:

public class AuthWhereRole : AuthorizeAttribute { /// <summary> /// Add the allowed roles to this property. /// </summary> public UserRole Is; /// <summary> /// Checks to see if the user is authenticated and has the /// correct role to access a particular view. /// </summary> /// <param name="httpContext"></param> /// <returns></returns> 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 todos tengan un valor de 1 en adelante. Me gusta esto:

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

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

Bueno, espero que esto ayude un poco.


O podrías concatenar como:

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


Para agregar al código de CalebHC y responder a 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 tenemos que convertir todas las cadenas de la matriz que coincidan 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 autorizado".

Toda la clase se ve así:

[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, Inherited = true, AllowMultiple = true)] public class CustomAuthorizeAttribute : AuthorizeAttribute { /// <summary> /// Add the allowed roles to this property. /// </summary> public Roles Is { get; set; } /// <summary> /// Checks to see if the user is authenticated and has the /// correct role to access a particular view. /// </summary> /// <param name="httpContext"></param> /// <returns></returns> 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<Roles>().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" }; } }


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(); } }