2012-01-09 20 views
11

Tengo un escenario donde tengo que manejar la autenticación de solicitudes ajax usando "Autenticación de formularios". Basado en alguna búsqueda y ayuda de mi publicación anterior de stackoverflow, decidí usar el método descrito en here.Código de respuesta 401 activando la autenticación básica antes del controlador de error jquery ajax

La idea es enviar de vuelta una respuesta 401 para solicitudes no autenticadas, y luego manejar eso en el controlador de error AJAX. Así que tengo un controlador de errores AJAX en mi página ASP.NET MVC3 Layout que redirige el navegador a la página de inicio de sesión cuando recibe la respuesta 401 en solicitudes ajax no autenticadas. Aquí está el controlador de errores ajax.

$(document).ajaxError(function (event, jqXHR, ajaxSettings, thrownError) { 
    if (jqXHR.status == "401") { 
     window.location.replace(loginUrl); 
    } 
    .... 
}); 

Todo esto funciona bien en mi servidor local IIS 7.5. Pero en el servidor donde está alojado mi sitio, desafortunadamente, recibo una ventana emergente de autenticación básica sobre solicitudes ajax no autenticadas (por ejemplo, tiempo de espera agotado), antes de que el manejador de errores AJAX se ejecute y redirija el navegador a la página de inicio de sesión. Cuando cancelo la ventana emergente "Autenticación requerida" presionando el botón Cancelar, el controlador de error AJAX se ejecuta y me redireccionan a la página de inicio de sesión.

Entonces, ¿por qué el navegador muestra la ventana emergente de autenticación antes de ejecutar el controlador de errores AJAX?

Editar: el servidor que aloja ejecuta IIS 6.

+0

tener cuidado siguiendo el enlace en este texto de la pregunta anterior "aquí" ... se informa de una infección troyano. – hal9000

Respuesta

0

intenta quitar cabecera WWW-Identificación de la respuesta.

+0

Intenté eliminar el encabezado "WWW-Authenticate" de la respuesta utilizando response.Headers.Remove ("WWW-Authenticate") en el controlador de eventos "EndRequest" de IHttpModule, pero el código arroja [PlatformNotSupportedException: Esta operación requiere IIS modo de tubería integrada.]. Por lo tanto, dudo que podamos eliminar los encabezados de la respuesta. – Jatin

+1

Puede usar los métodos response.Headers solo en el modo de canalización integrada IIS7, use los métodos response.ClearHeaders() y response.AppendHeader() en IIS 6 – ladoch

0

IIS 6 en modo integrado? No creo que exista tal cosa, a menos que esté hablando de autenticación integrada.

Supongo que está utilizando una extensión que no es aspx, por lo que en IIS6 esto significa que ni siquiera está llegando al proceso .net. Entonces, IIS está usando su propia página de respuesta de error 401.

Probablemente, la solución es forzar todas las solicitudes para ser manejadas por el proceso .net.

Su host tendrá que ir a propiedades de IIS> configuración> asignaciones de comodines, y mapear todo al proceso .net.

+0

ScottE, disculpe la información incorrecta, de hecho, IIS 6 no tiene el modo de canalización integrado. De todos modos, con respecto a su suposición, tengo una implementación IHttpModule, pero está haciendo lo que se supone que debe hacer, es decir, devolver la respuesta 401 para solicitudes ajax no autenticadas. No hay otra extensión que no sea aspx para gestionar solicitudes, así que supongo que la solicitud está siendo procesada por el proceso .net. Puede encontrar la implementación de IHttpModule que estoy usando en el enlace provisto en mi pregunta. Gracias por responder. – Jatin

+0

No, en IIS 6, de manera predeterminada, el proceso .net no maneja las URL sin extensión. Entonces, la solicitud ni siquiera está llegando a su httpmodule. Si .net maneja todas las solicitudes, entonces deberías estar bien. – ScottE

+0

La autenticación funciona bien para solicitudes que no son Ajax. Estoy usando la autenticación de formularios y si hay una solicitud no autenticada (no ajax), se me redirige correctamente a la página de inicio de sesión. Después de iniciar sesión, en Yo puedo acceder a todos los métodos de acción del controlador MVC de asp.net. El problema solo ocurre para las solicitudes ajax no autenticadas, donde estoy enviando una respuesta 401 desde mi módulo.Desafortunadamente, IIS 6 agrega dos encabezados "WWW-Authenticate" con el valor de "Negotiate" y "NTLM", lo que hace que el navegador active la ventana emergente de autenticación. – Jatin

0

.net no detectará los errores 401. Lo que hice fue establecer la página de error de IIS de la página 401 predeterminada en mi propia página 401 estática. Desde esa página utilicé javascript para redirigir a otro controlador.

1

Esta es una pregunta frecuente con una respuesta fácil. el 401 se transforma en un 302 en la página de inicio de sesión mediante el módulo de autorización .net. El navegador nunca ve el 401 solo el 302.

Por supuesto, esto no está jugando muy bien con las llamadas ajax.

La mejor solución que probé y que estoy usando involucra la escritura de un nuevo atributo que está capturando 401 y transformándolo en ... 409 que está atrapado por el manejador jquery ajax.

Es parte de un producto pago por lo que no puedo dar ningún código.

+0

Ya he manejado la supresión de la transformación 401 a 302. Pero al final estaba devolviendo 401, y eso está activando la ventana emergente requerida de autenticación en el navegador. Hoy traté de devolver un código de error personalizado, digamos 601 en vez de 401 y luego lo manejé en el manejador de errores jquery ajax. Esto parece funcionar en mi servidor de almacenamiento intermedio, pero ¿puede haber algún inconveniente en este enfoque? – Jatin

+1

Sí, use 409, en cambio, es más seguro. 4xx son errores de autenticación (normalizados). 6xx no está normalizado. "La clase 4xx de código de estado está diseñada para casos en los que el cliente parece tener errores". ver http://en.wikipedia.org/wiki/List_of_HTTP_status_codes. Uso 409 porque prefiero usar un código de error que existe ya que puede no haber soporte en algunos navegadores para códigos de retorno http no existentes. Mis pruebas muestran que 409 está bien soportado en los navegadores IE, Chrome, FF y Safari, y no activa ninguna función especial del navegador (302 lo hace). – Softlion

-1

¡Espera! Pensé que habías dicho la solicitud de Ajax, ¿cómo puedes obtener una ventana emergente en una solicitud de Ajax? Estoy bastante seguro de que estás desencadenando la llamada a la URL incluso antes de la llamada AJAX. Desde su escenario, demostró que cuando cancela la ventana emergente, se realiza su solicitud real de ajax y, por lo tanto, puede hacer una redirección ajax.

La idea es enviar de vuelta una respuesta 401 de las solicitudes no autenticadas, y luego manejar que en el gestor de errores de AJAX

Usted puede obtener una respuesta Ajax sólo si se envía una solicitud de ajax, si envía una solicitud http normal, entonces obtendrás una ventana emergente. Esto no tiene nada que ver con .Net o Java :)

+3

No sé si una solicitud de Ajax, que devuelve 401 respuestas, debería activar el navegador para mostrar la ventana emergente de autenticación, pero ocurre. Estoy realizando una solicitud de ajax pura no autenticada y devolviendo la respuesta 401, y esto hace que el navegador muestre la ventana emergente de "Autenticación requerida". Si devuelvo algún código de respuesta personalizado (por ejemplo, 601) para la solicitud ajax no autenticada, el navegador no muestra la ventana emergente "Requerido autenticado". Sin embargo, el controlador de error ajax se ejecuta y podría usarlo para redirigir el navegador a la URL de inicio de sesión utilizando la solicitud normal. Este enfoque parece funcionar – Jatin

+0

Realmente la idea era enviar un código de respuesta válido a través de ajax y manejarlo en el controlador de devolución de llamada y redirigir :) – Abhi

0

La solución here es escribir un HttpModule personalizado para solucionar el comportamiento predeterminado de los frameworks MVC. Una vez que finalmente pude registrar el módulo (cheers David Ebbo) funcionó para mí. Es posible que desee elegir su propio criterio para llamar al SuppressAuthenticationRedirect.

public class SuppressFormsAuthenticationRedirectModule : IHttpModule { 
    private static readonly object SuppressAuthenticationKey = new Object(); 

    public static void SuppressAuthenticationRedirect(HttpContext context) { 
    context.Items[SuppressAuthenticationKey] = true; 
    } 

    public static void SuppressAuthenticationRedirect(HttpContextBase context) { 
    context.Items[SuppressAuthenticationKey] = true; 
    } 

    public void Init(HttpApplication context) { 
    context.PostReleaseRequestState += OnPostReleaseRequestState; 
    context.EndRequest += OnEndRequest; 
    } 

    private void OnPostReleaseRequestState(object source, EventArgs args) { 
    var context = (HttpApplication)source; 
    var response = context.Response; 
    var request = context.Request; 

    if (response.StatusCode == 401 && request.Headers["X-Requested-With"] == 
     "XMLHttpRequest") { 
     SuppressAuthenticationRedirect(context.Context); 
    } 
    } 

    private void OnEndRequest(object source, EventArgs args) { 
    var context = (HttpApplication)source; 
    var response = context.Response; 

    if (context.Context.Items.Contains(SuppressAuthenticationKey)) { 
     response.TrySkipIisCustomErrors = true; 
     response.ClearContent(); 
     response.StatusCode = 401; 
     response.RedirectLocation = null; 
    } 
    } 

    public void Dispose() { 
    } 

    public static void Register() { 
    DynamicModuleUtility.RegisterModule(
     typeof(SuppressFormsAuthenticationRedirectModule)); 
    } 
} 
2

como Softlion dijo

Ésta es una pregunta común con una respuesta fácil. el 401 se transforma en un 302 en la página de inicio de sesión mediante el módulo de autorización .net. El navegador no ver el 401 sólo el 302.

si está utilizando .NET 4 y posteriores, use el código de abajo

HttpContext.Response.SuppressFormsAuthenticationRedirect = true; 

Es un trabajo muy bien para mí.

0

Para mí, esto terminó siendo simple. La mayoría de los sitios web de IIS con autenticación anónima también tienen un defecto de Windows autenticación habilitada

Authentication configuration

Apague la autenticación de Windows que es la que aparece la pantalla de inicio de sesión cuando el sitio detecta el 401 incluso de una llamada AJAX.

<security> <authentication> <anonymousAuthentication enabled="true" /> <windowsAuthentication enabled="false" /> </authentication> </security>

Cuestiones relacionadas