Autorización personalizada en Asp.net WebApi: ¿qué lío?

Estoy leyendo varios recursos (libros y respuestas SO) sobre la autorización en WebApi.

Supongamos que deseo agregar un atributo personalizado que permita el acceso solo a ciertos usuarios:

Caso 1

He visto este enfoque de reemplazar OnAuthorization , que establece la respuesta si algo está mal

 public class AllowOnlyCertainUsers : AuthorizeAttribute { public override void OnAuthorization(HttpActionContext actionContext) { if ( /*check if user OK or not*/) { actionContext.Response = new HttpResponseMessage(HttpStatusCode.Unauthorized); } } } 

Caso # 2

Pero también he visto este ejemplo similar que también OnAuthorization pero con llamadas a base :

 public override void OnAuthorization(HttpActionContext actionContext) { base.OnAuthorization(actionContext); // If not authorized at all, don't bother if (actionContext.Response == null) { //... } } 

Luego, verifica si HttpActionContext.Response está configurado o no. Si no está configurado, significa que la solicitud está autorizada y el usuario está bien.

Caso # 3

Pero también he visto este enfoque de anular IsAuthorized :

 public class AllowOnlyCertainUsers : AuthorizeAttribute { protected override bool IsAuthorized(HttpActionContext context) { if ( /*check if user OK or not*/) { return true;// or false } } } 

Caso # 4

Y luego vi un ejemplo similar uno pero con una base de llamadas. Está autorizado (contexto):

 protected override bool IsAuthorized(HttpActionContext context) { if (something1 && something2 && base.IsAuthorized(context)) //?? return true; return false; } 

Una cosa más

Y finalmente Dominick dijo aquí :

No debe anular OnAuthorization: porque le faltaría el manejo de [AllowAnonymous].

Preguntas

  • 1) ¿Qué métodos debo usar: ¿está IsAuthorized o OnAuthorization ? (o cuándo usar cuál)

  • 2) ¿cuándo debo llamar a base.IsAuthorized or base.OnAuthorization`?

  • 3) ¿Es así como lo construyeron? que si la respuesta es nula, entonces todo está bien? (caso n. ° 2)

nótese bien

Tenga en cuenta que estoy usando (y quiero usar) solo AuthorizeAttribute que ya hereda de AuthorizationFilterAttribute

Por qué ?

Porque estoy en la primera etapa en: http://www.asp.net/web-api/overview/security/authentication-and-authorization-in-aspnet-web-api

enter image description here

De todos modos estoy preguntando a través de extender el atributo Autorizar.

¿Qué métodos debo usar: ¿está autorizada o autorizada? (o cuándo usar cuál)

Extenderá AuthorizationFilterAttribute si su lógica de autorización no depende de la identidad establecida y los roles. Para la autorización relacionada con el usuario, extenderá y usará AuthorizeAttribute . Para el primer caso, anulará OnAuthorization . Para este último caso, anulará IsAuthorized . Como puede ver en el código fuente de estos atributos, OnAuthorization se marca como virtual para que lo sobrescriba si deriva de AuthorizationFilterAttribute . Por otro lado, el método IsAuthorized se marca como virtual en AuthorizeAttribute . Creo que este es un buen indicador del uso previsto.

¿Cuándo debo llamar a base.Is autorizado o base.OnAutorización?

La respuesta a esta pregunta radica en cómo OO generalmente funciona. Si anula un método, puede proporcionar completamente una nueva implementación o aprovechar la implementación proporcionada por los padres y mejorar el comportamiento. Por ejemplo, tome el caso de IsAuthorized(HttpActionContext) . El comportamiento de la clase base es verificar el usuario / rol contra lo que se especifica en el filtro versus la identidad establecida. Supongamos que quiere hacer todo eso, pero además, desea verificar algo más, puede basarse en un encabezado de solicitud o algo así. En ese caso, puede proporcionar una anulación como esta.

 protected override bool IsAuthorized(HttpActionContext actionContext) { bool isAuthroized = base.IsAuthorized(actionContext); // Here you look at the header and do your additional stuff based on actionContext // and store the result in isRequestHeaderOk // Then, you can combine the results // return isAuthorized && isRequestHeaderOk; } 

Lo siento pero no entiendo tu Q3. Por cierto, el filtro de Autorización ha existido por mucho tiempo y la gente lo usa para todo tipo de cosas y, a veces incorrectamente también.

Una cosa más. Y finalmente estaba este tipo que dijo: No debe anular la Autorización de autorización, porque le faltaría el manejo de [AllowAnonymous].

El chico que dijo eso es el Dios del control de acceso: Dominick. Obviamente será correcto. Si observa la implementación de OnAuthorization (copiada a continuación),

 public override void OnAuthorization(HttpActionContext actionContext) { if (actionContext == null) { throw Error.ArgumentNull("actionContext"); } if (SkipAuthorization(actionContext)) { return; } if (!IsAuthorized(actionContext)) { HandleUnauthorizedRequest(actionContext); } } 

la llamada a SkipAuthorization es la parte que garantiza que se AllowAnonymous filtros AllowAnonymous , es decir, que se AllowAnonymous autorización. Si anulas este método, pierdes ese comportamiento. En realidad, si decide basar su autorización en usuarios / roles, en ese momento habría decidido derivar de AuthorizeAttribute . La única opción correcta que le queda en ese momento será anular IsAuthorized y no la OnAuthorization ya anulada, aunque técnicamente es posible hacerlo.

PD. En ASP.NET Web API, hay otro filtro llamado filtro de autenticación. La idea es que la use para el filtro de autenticación y autorización para autorización, como su nombre indica. Sin embargo, hay muchos ejemplos en los que este límite está borroso. Muchos ejemplos de filtros de autenticación harán algún tipo de autenticación. De todos modos, si tiene tiempo y quiere entender un poco más, eche un vistazo a este artículo de MSDN. Descargo de responsabilidad: Fue escrito por mí.

De acuerdo, mi sugerencia es hacer lo siguiente, suponiendo que está utilizando tokens de portador de OAuth para proteger su API web y que está estableciendo el tiempo permitido como reclamo para el usuario cuando emitió el token. Puede leer más sobre la autenticación basada en tokens aquí

  1. Crear CustomAuthorizeAttribute que se deriva de AuthorizationFilterAttribute
  2. reemplaza el método OnAuthorizationAsync y usa el siguiente código de muestra:

      public class CustomAuthorizeAttribute : AuthorizationFilterAttribute { public override Task OnAuthorizationAsync(HttpActionContext actionContext, System.Threading.CancellationToken cancellationToken) { var principal = actionContext.RequestContext.Principal as ClaimsPrincipal; if (!principal.Identity.IsAuthenticated) { return Task.FromResult(null); } var userName = principal.FindFirst(ClaimTypes.Name).Value; var userAllowedTime = principal.FindFirst("userAllowedTime").Value; if (currentTime != userAllowedTime) { actionContext.Response = actionContext.Request.CreateResponse(HttpStatusCode.Unauthorized, "Not allowed to access...bla bla"); return Task.FromResult(null); } //User is Authorized, complete execution return Task.FromResult(null); } } 
  3. Ahora en sus controladores utiliza el atributo CustomAuthorize para proteger sus controladores utilizando esta lógica de autorización.

ASP.NET v5 introdujo un sistema de autorización completamente nuevo. Para aquellos que van a usar .NET 5 sugeriría pasar a Microsoft.AspNet.Authorization.

Prácticamente termina el lío provocado por mantener System.Web.Http.Authorize y System.Web.Mvc.Authorize y otras implementaciones de autenticación antiguas.

Proporciona una muy buena abstracción de los tipos de acción (Crear, Leer, Actualizar, Eliminar), Recursos, Roles, Reclamos, Vistas, Requisitos personalizados y permite crear Controladores personalizados, combinando cualquiera de los anteriores. Además, esos manipuladores se pueden usar en combinación también.

En ASP.NET v5 la autorización ahora proporciona un rol declarativo simple y un modelo más rico basado en políticas donde la autorización se expresa en requisitos y los manejadores evalúan las reclamaciones de los usuarios contra los requisitos. Las verificaciones imperativas pueden basarse en políticas o políticas simples que evalúan tanto la identidad del usuario como las propiedades del recurso al que el usuario intenta acceder.