2010-05-28 8 views
14

Me gustaría generar una página 401 si el usuario no tiene el permiso correcto.Cómo interceptar 401 desde la autenticación de formularios en ASP.NET MVC?

El usuario solicita una url y se le redirige a la página de inicio de sesión (he denegado todo anónimo en web.config). El usuario inicia sesión correctamente y se redirige a la url original. Sin embargo, al comprobar el permiso, se determina que el usuario no tiene el permiso requerido, por lo que me gustaría generar un 401. Pero la autenticación de formularios siempre maneja 401 y redirige al usuario a la página de inicio de sesión.

Para mí, esto no es correcto. El usuario ya ha autenticado , el usuario simplemente no tiene la autorización correcta.

En otros escenarios, como en ajax o escenario de servicio REST, definitivamente no quiero la página de inicio de sesión, necesito la página 401 adecuada.

Hasta ahora, he intentado personalizar el filtro Autorizar para devolver ViewResult con 401 pero no funcionó. Luego probé un filtro de acción normal, anulando OnActionExecuting, que tampoco funcionaba.

Lo que pude hacer es controlar un evento en global.asax, PostRequestHandlerExecute, y compruebe si el permiso luego escribir directamente a la respuesta:

if (permissionDenied) 
{ 
    Context.Response.StatusCode = 401; 
    Context.Response.Clear(); 
    Context.Response.Write("Permission Denied"); 
    Context.Response.Flush(); 
    Context.Response.Close(); 
    return; 
} 

que funciona, pero no es realmente lo que quiero. Antes que nada, ni siquiera estoy seguro de si ese es el evento correcto o el lugar en la tubería para hacer eso. En segundo lugar, quiero que la página 401 tenga un poco más de contenido. Preferiblemente, debería ser una página aspx con posiblemente la misma página maestra que el resto del sitio. De esta forma, cualquier persona que navegue por el sitio puede ver que se deniega el permiso pero con la misma apariencia, etc., pero el usuario de Ajax o del servicio obtendrá el código de estado adecuado para actuar.

¿Alguna idea de cómo se puede lograr esto? He visto otras publicaciones con solicitudes similares, pero no vi una solución que pueda usar.

Y no, no quiero un 403.

Respuesta

8

Encontré una solución factible.

401 de redireccionamiento por FormsAuthenticationModule se produce durante EndRequest. Dado que durante el procesamiento de eventos, los módulos se invocan antes de global.asax, podemos anular el código de estado después de FormsAuthenticationModule ha tenido sus sucias manos en la solicitud.

En mi AuthorizationFilter encargo, puse HttpContext.Items [ "PermissionDenied"] true y luego en mi global.asaxEndRequest, me tapa el código de estado de 200 a 401. Entonces servidor Transfiera a mi vista PermissionDenied personalizada.

Todavía preferiría FormsAuthenticationModule en sí mismo se actualizó para manejar este escenario, pero creo que esto no es demasiado hackish que creo que puedo vivir con ello.

Obviamente, puede cambiar la forma en que señala que global.asax debe voltear el código de estado. Simplemente intenté configurar el código de estado en algo así como 511 y lo usé como la condición en lugar de HttpContext.Items y eso funcionó también. Supongo que mientras el código de estado correcto salga por la puerta, al motor ASP.NET no le importa.

0

Es posible que desee ver aquí: ASP.NET MVC Custom Error Handling Application_Error Global.asax?

Usted debe ser capaz de coger el 401 y el camino a una acción personalizada en ese punto. Estamos haciendo esto para 404 y otras excepciones en nuestro código, y está funcionando muy bien.

+0

No estoy seguro de a cuál de las respuestas me está dirigiendo. En cualquier caso, no quiero volver a enrutar o redirigir porque entonces mi estado de respuesta no será 401 - será algo así como 302 seguido de 200, que no es lo que esperaría si estuviera accediendo a la url de un cliente ajax –

+0

Jiho - Me disculpo, no leí la pregunta lo suficientemente cerca. Pensé que solo estabas tratando de hacer una redirección 401 personalizada. – Robaticus

2

Acepto que el comportamiento predeterminado es incorrecto, especialmente teniendo en cuenta las solicitudes de Ajax. Espero ver algún tipo de solución en MVCv3 (dedos cruzados).

La única manera que conozco para lograr esto es eliminar la sección Autenticación de la web.config, esto es lo que busca ASP.NET para redirigir las solicitudes no autorizadas. No puede desactivar esta "característica", que yo sepa. Si tiene una sección de autenticación, se le redirigirá a la url de inicio de sesión si ASP.NET alguna vez encuentra un código de estado 401.

Pero al eliminar esto, tiene otros problemas. Si alguna vez desea que el usuario sea redirigido a la página de inicio de sesión para solicitudes que no sean Ajax, deberá implementar su propio AuthorizeAttribute y usar una configuración personalizada para determinar a dónde debe redireccionar. Además, cualquier otra cosa en la sección de Autenticación probablemente también deba ser reimplementada por usted. No es una solución muy práctica en sitios complicados.

No he hecho esto yo mismo, me conformé con devolver un 403 en su lugar. Es molesto no tener el HttpCode correcto devuelto, pero es mejor que cualquier otra solución que he encontrado hasta ahora.

+2

tiene razón: acabo de tomar Reflector en FormsAuthenticationModule y en el manejo de EndRequest comprueba 401 y redirige. No parece que haya una manera de anular este comportamiento tampoco. –

+0

Sí, los 403 ya no suenan tan mal :) – Jab

5
HttpContext.Current.Response.SuppressFormsAuthenticationRedirect = true; 
Cuestiones relacionadas