Asp.net MVC4: autorizar tanto el controlador como la acción

Si tengo el atributo Autorizar tanto en el controlador como en la acción, ¿cuál tendrá el efecto? ¿O ambos tendrán efecto?

    Tu preguntaste:

    Si tengo el atributo Autorizar tanto en el controlador como en la acción, ¿cuál tendrá el efecto? ¿Ambos?

    Para responder esto simplemente: Ambos. El efecto es para AND las dos restricciones juntas. Explicaré por qué a continuación …

    Detalles

    Entonces, hay algunas razones por las que podrías estar preguntándote esto.

    1. Desea saber cómo aplicar una restricción adicional en una Acción en comparación con un método. p.ej
      • A nivel de controlador, imponer a los usuarios el rol de “usuario”
      • En un nivel de acción, además, impone a los usuarios el rol “admin”
    2. Desea reemplazar la restricción del controlador en el nivel de acción
    3. Desea eliminar la restricción del controlador en el nivel de acción y poner el método a disposición de los usuarios anónimos

    No especificó su versión de MVC, así que asumiré la última a partir de hoy (MVC 4.5). Sin embargo, eso no cambiará la respuesta mucho, incluso si estuviera usando MVC 3.

    [Anonymous] anula el controlador [Authorize] (caso 3)

    Caso 3. No necesito cubrir (el uso de [AllowAnonymous] ) ya que ha sido respondido en todo SO y toda la web ya. Basta con decir: si especifica [AllowAnonymous] en una acción, la hará pública incluso si el controlador tiene [Authorize] en ella.

    También puede hacer que un sitio web completo esté sujeto a autorización mediante el uso de un filtro global , y use AllowAnonymous en las pocas acciones o controladores que desea hacer públicos.

    [Authorize] es aditivo (caso 1)

    El caso 1 es fácil. Tome el siguiente controlador como un ejemplo:

     [Authorize(Roles="user")] public class HomeController : Controller { public ActionResult AllUsersIndex() { return View(); } [Authorize(Roles = "admin")] public ActionResult AdminUsersIndex() { return View(); } } 

    Por defecto [Authorize(Roles="user")] hace que todas las acciones en el controlador estén disponibles para las cuentas en el rol de “usuario” solamente. Por lo tanto, para acceder a AllUsersIndex debe estar en el rol de “usuario”. Sin embargo, para acceder a AdminUsersIndex debe estar tanto en el rol de “usuario” como en el de “administrador”. Por ejemplo:

    • AdminUsersIndex usuario: Bob, Roles: usuario, no puede acceder a AdminUsersIndex , pero puede acceder a AllUsersIndex
    • AdminUsersIndex AllUsersIndex : Jane, Roles: admin, no puede acceder a AdminUsersIndex o AllUsersIndex
    • Nombre de usuario: Tim, Roles: usuario y administrador, puede acceder a AdminUsersIndex y AllUsersIndex

    Esto ilustra que el atributo [Authorize] es aditivo. Esto también es cierto para la propiedad de los Users del atributo, que se puede combinar con Roles para hacerlo aún más restrictivo.

    Este comportamiento se debe a la forma en que funcionan los atributos de controlador y acción. Los atributos se encadenan entre sí y se aplican en el controlador de la orden y luego en la acción. Si el primero rechaza la autorización, el control regresa y no se llama al atributo de la acción. Si el primero aprueba la autorización, entonces también se verifica el segundo. Puede anular este orden especificando Order (por ejemplo [Authorize(Roles = "user", Order = 2)] ).

    Anulación [Authorize] (caso 2)

    El caso 2 es más complicado. Recuerde desde arriba que los atributos [Authorize] se examinan en el orden (Global luego) Controlador luego Acción. El primero en detectar que el usuario es inelegible para ser autorizado gana, los otros no reciben una llamada.

    Una forma de evitar esto es definir dos atributos nuevos a continuación. [OverrideAuthorize] no hace más que diferir a [Authorize] ; su único propósito es definir un tipo que podamos verificar. La [DefaultAuthorize] nos permite verificar si la Acción que se llama en la solicitud está decorada con [OverrideAuthorize] . Si es así, diferimos a la verificación de autorización de Acción; de lo contrario, procedemos con la verificación de nivel del Controlador.

     public class DefaultAuthorizeAttribute : AuthorizeAttribute { public override void OnAuthorization(AuthorizationContext filterContext) { var action = filterContext.ActionDescriptor; if (action.IsDefined(typeof(OverrideAuthorizeAttribute), true)) return; base.OnAuthorization(filterContext); } } public class OverrideAuthorizeAttribute : AuthorizeAttribute { public override void OnAuthorization(AuthorizationContext filterContext) { base.OnAuthorization(filterContext); } } 

    Entonces podemos usarlo así:

     [DefaultAuthorize(Roles="user")] public class HomeController : Controller { // Available to accounts in the "user" role public ActionResult AllUsersIndex() { return View(); } // Available only to accounts both in the "user" and "admin" role [Authorize(Roles = "admin")] public ActionResult AdminUsersIndex() { return View(); } // Available to accounts in the "superuser" role even if not in "user" role [OverrideAuthorize(Roles = "superuser")] public ActionResult SuperusersIndex() { return View(); } } 

    En el ejemplo anterior, SuperusersIndex está disponible para una cuenta que tiene el rol de “superusuario”, incluso si no tiene el rol de “usuario”.

    Me gustaría agregar algo a Overriding [Authorize] (case 2)

    OverrideAuthorizeAttribute y DefaultAuthorizeAttribute funcionan bien, pero descubro que también puede usar OverrideAuthorizationAttribute que anula los filtros de autorización definidos en un nivel superior.

     [Authorize(Roles="user")] public class HomeController : Controller { // Available to accounts in the "user" role public ActionResult AllUsersIndex() { return View(); } // Available only to accounts both in the "user" and "admin" role [Authorize(Roles = "admin")] public ActionResult AdminUsersIndex() { return View(); } // Available to accounts in the "superuser" role even if not in "user" role [OverrideAuthorization()] [Authorize(Roles = "superuser")] public ActionResult SuperusersIndex() { return View(); } } 

    Si lo usa en el controlador, todos los métodos de este controlador se verán afectados.

     [Authorize] public class SomeController(){ // all actions are effected public ActionResult Action1 public ActionResult Action2 

    Si desea evitar una de estas acciones, puede usar algo como esto:

     [Authorize] public class SomeController(){ // all actions are effected public ActionResult Action1 public ActionResult Action2 [AllowAnonymous] public ActionResult Action3 // only this method is not effected...