En ASP.NET MVC, puede marcar un método de controlador con AuthorizeAttribute
, como este:
[Authorize(Roles = "CanDeleteTags")]
public void Delete(string tagName)
{
// ...
}
Esto significa que, si el usuario conectado actualmente no está en el rol "CanDeleteTags", nunca se llamará al método del controlador.
Desafortunadamente, para fallas, AuthorizeAttribute
retornos HttpUnauthorizedResult
, que siempre devuelve el código de estado HTTP 401. Esto provoca una redirección a la página de inicio de sesión.
Si el usuario no ha iniciado sesión, esto tiene mucho sentido. Sin embargo, si el usuario ya ha iniciado sesión, pero no está en el rol requerido, es confuso enviarlo nuevamente a la página de inicio de sesión.
Parece que AuthorizeAttribute
combina la autenticación y la autorización.
Esto parece un poco un descuido en ASP.NET MVC, ¿o me falta algo?
He tenido que cocinar una DemandRoleAttribute
que separe a los dos. Cuando el usuario no está autenticado, devuelve HTTP 401 y lo envía a la página de inicio de sesión. Cuando el usuario inicia sesión, pero no está en el rol requerido, crea un NotAuthorizedResult
lugar. Actualmente esto redirige a una página de error.
¿Seguramente no tuve que hacer esto?
fuente
Respuestas:
Cuando se desarrolló por primera vez, System.Web.Mvc.AuthorizeAttribute estaba haciendo lo correcto: las revisiones anteriores de la especificación HTTP usaban el código de estado 401 tanto para "no autorizado" como "no autenticado".
De la especificación original:
De hecho, puede ver la confusión allí mismo: utiliza la palabra "autorización" cuando significa "autenticación". Sin embargo, en la práctica diaria, tiene más sentido devolver un 403 Prohibido cuando el usuario está autenticado pero no autorizado. Es poco probable que el usuario tenga un segundo conjunto de credenciales que les otorgue acceso, mala experiencia del usuario en general.
Considere la mayoría de los sistemas operativos: cuando intenta leer un archivo al que no tiene permiso de acceso, no se le muestra una pantalla de inicio de sesión.
Afortunadamente, las especificaciones HTTP se actualizaron (junio de 2014) para eliminar la ambigüedad.
Desde "Protocolo de transporte de hipertexto (HTTP / 1.1): Autenticación" (RFC 7235):
Del "Protocolo de transferencia de hipertexto (HTTP / 1.1): semántica y contenido" (RFC 7231):
Curiosamente, en el momento en que se lanzó ASP.NET MVC 1, el comportamiento de AuthorizeAttribute era correcto. Ahora, el comportamiento es incorrecto: se corrigió la especificación HTTP / 1.1.
En lugar de intentar cambiar las redirecciones de la página de inicio de sesión de ASP.NET, es más fácil solucionar el problema en la fuente. Puede crear un nuevo atributo con el mismo nombre (
AuthorizeAttribute
) en el espacio de nombres predeterminado de su sitio web (esto es muy importante), luego el compilador lo recogerá automáticamente en lugar del estándar de MVC. Por supuesto, siempre podría darle un nuevo nombre al atributo si prefiere adoptar ese enfoque.fuente
filterContext.HttpContext.User.Identity.IsAuthenticated
, simplemente puede verificarfilterContext.HttpContext.Request.IsAuthenticated
, que viene con cheques nulos integrados. Consulte stackoverflow.com/questions/1379566/…Agregue esto a su función de carga de página de inicio de sesión:
Cuando el usuario es redirigido allí pero ya ha iniciado sesión, muestra la página no autorizada. Si no han iniciado sesión, falla y muestra la página de inicio de sesión.
fuente
if (User.Identity != null && User.Identity.IsAuthenticated) return RedirectToRoute("Unauthorized");
cuando no autorizada es un nombre de ruta definida.Siempre pensé que esto tenía sentido. Si ha iniciado sesión e intenta acceder a una página que requiere un rol que no tiene, se le reenvía a la pantalla de inicio de sesión y le solicita que inicie sesión con un usuario que sí lo tiene.
Puede agregar lógica a la página de inicio de sesión que verifica si el usuario ya está autenticado. Podría agregar un mensaje amistoso que explique por qué los han vuelto a tocar.
fuente
Desafortunadamente, está lidiando con el comportamiento predeterminado de la autenticación de formularios ASP.NET. Hay una solución alternativa (no lo he probado) discutida aquí:
http://www.codeproject.com/KB/aspnet/Custon401Page.aspx
(No es específico de MVC)
Creo que, en la mayoría de los casos, la mejor solución es restringir el acceso a recursos no autorizados antes de que el usuario intente llegar allí. Al eliminar / atenuar el enlace o botón que podría llevarlos a esta página no autorizada.
Probablemente sería bueno tener un parámetro adicional en el atributo para especificar dónde redirigir a un usuario no autorizado. Pero mientras tanto, miro el AuthorizeAttribute como una red de seguridad.
fuente
Intente esto en su controlador Application_EndRequest de su archivo Global.ascx
fuente
Si usa aspnetcore 2.0, use esto:
fuente
En mi caso, el problema era "la especificación HTTP utilizaba el código de estado 401 tanto para" no autorizado "como para" no autenticado ". Como dijo ShadowChaser.
Esta solución me funciona:
fuente