Estoy usando $.post()
para llamar a un servlet usando Ajax y luego usando el fragmento HTML resultante para reemplazar un div
elemento en la página actual del usuario. Sin embargo, si la sesión agota el tiempo de espera, el servidor envía una directiva de redireccionamiento para enviar al usuario a la página de inicio de sesión. En este caso, jQuery está reemplazando eldiv
elemento con el contenido de la página de inicio de sesión, lo que obliga a los ojos del usuario a presenciar una escena rara.
¿Cómo puedo administrar una directiva de redireccionamiento desde una llamada Ajax con jQuery 1.2.6?
javascript
jquery
ajax
redirect
Elliot Vargas
fuente
fuente
HttpContext.Response.AddHeader
y comprobar en el éxito de ajaxsetup es el camino a seguirRespuestas:
Leí esta pregunta e implementé el enfoque que se ha establecido con respecto a la configuración del código de estado HTTP de respuesta a 278 para evitar que el navegador maneje de forma transparente las redirecciones. Aunque esto funcionó, estaba un poco insatisfecho ya que es un poco hack.
Después de investigar más, abandoné este enfoque y usé JSON . En este caso, todas las respuestas a las solicitudes AJAX tienen el código de estado 200 y el cuerpo de la respuesta contiene un objeto JSON que se construye en el servidor. El JavaScript en el cliente puede usar el objeto JSON para decidir qué necesita hacer.
Tuve un problema similar al tuyo. Realizo una solicitud AJAX que tiene 2 respuestas posibles: una que redirige el navegador a una nueva página y otra que reemplaza un formulario HTML existente en la página actual por uno nuevo. El código jQuery para hacer esto se parece a:
El objeto "datos" JSON se construye en el servidor para tener 2 miembros:
data.redirect
ydata.form
. Encontré este enfoque mucho mejor.fuente
Resolví este problema de la siguiente manera:
Agregar un encabezado personalizado a la respuesta:
Vinculando una función de JavaScript al
ajaxSuccess
evento y verificando si existe el encabezado:fuente
Ningún navegador maneja las respuestas 301 y 302 correctamente. Y, de hecho, el estándar incluso dice que deberían manejarlos "transparentemente", lo cual es un dolor de cabeza MASIVO para los vendedores de la Biblioteca Ajax. En Ra-Ajax nos vimos obligados a usar el código de estado de respuesta HTTP 278 (solo un código de éxito "no utilizado") para manejar redirecciones transparentes desde el servidor ...
Esto realmente me molesta, y si alguien aquí tiene algo de "atracción" en el W3C, ¡agradecería que pudieras hacerle saber al W3C que realmente necesitamos manejar nosotros mismos los códigos 301 y 302 ...! ;)
fuente
La solución que finalmente se implementó fue utilizar un contenedor para la función de devolución de llamada de la llamada Ajax y, en este contenedor, verificar la existencia de un elemento específico en el fragmento HTML devuelto. Si se encontró el elemento, el reiniciador ejecutó una redirección. De lo contrario, el reiniciador reenvió la llamada a la función de devolución de llamada real.
Por ejemplo, nuestra función de contenedor era algo así como:
Luego, al hacer la llamada Ajax, usamos algo como:
Esto funcionó para nosotros porque todas las llamadas de Ajax siempre devolvieron HTML dentro de un elemento DIV que usamos para reemplazar una parte de la página. Además, solo necesitábamos redirigir a la página de inicio de sesión.
fuente
Me gusta el método de Timmerz con un ligero toque de limón. Si alguna vez te devuelven contentType de text / html cuando esperas JSON , lo más probable es que estés siendo redirigido. En mi caso, simplemente vuelvo a cargar la página y se redirige a la página de inicio de sesión. Ah, y compruebe que el estado de jqXHR es 200, lo que parece una tontería, porque está en la función de error, ¿verdad? De lo contrario, los casos de error legítimos forzarán una recarga iterativa (oops)
fuente
Use la
$.ajax()
llamada de bajo nivel :Pruebe esto para una redirección:
fuente
Solo quería compartir mi enfoque ya que esto podría ayudar a alguien:
Básicamente incluí un módulo de JavaScript que maneja las cosas de autenticación como mostrar el nombre de usuario y también este caso manejando la redirección a la página de inicio de sesión .
Mi escenario: básicamente tenemos un servidor ISA en el medio que escucha todas las solicitudes y responde con un 302 y un encabezado de ubicación a nuestra página de inicio de sesión.
En mi módulo JavaScript mi enfoque inicial fue algo así como
El problema (como ya se mencionó aquí) es que el navegador maneja la redirección por sí mismo, por lo
ajaxComplete
que nunca se llamó a mi devolución de llamada, sino que recibí la respuesta de la página de inicio de sesión ya redirigida, que obviamente era unstatus 200
. El problema: ¿cómo detecta si la respuesta 200 exitosa es su página de inicio de sesión real o simplemente alguna otra página arbitraria?La solución
Como no pude capturar las respuestas de redireccionamiento 302, agregué un
LoginPage
encabezado en mi página de inicio de sesión que contenía la URL de la página de inicio de sesión. En el módulo ahora escucho el encabezado y hago una redirección:... y eso funciona como encanto :). Quizás se pregunte por qué incluyo la url en el
LoginPage
encabezado ... bueno, básicamente porque no encontré ninguna forma de determinar la urlGET
resultante de la redirección de ubicación automática desde elxhr
objeto ...fuente
X-
, por lo que sería mejor usar un encabezadoX-LoginPage: http://example.com/login
.X-
.Sé que este tema es antiguo, pero daré otro enfoque que he encontrado y descrito anteriormente aquí . Básicamente, estoy usando ASP.MVC con WIF (pero esto no es realmente importante para el contexto de este tema; la respuesta es adecuada sin importar qué marcos se usen. La pista permanece sin cambios: lidia con problemas relacionados con fallas de autenticación al realizar solicitudes ajax ) .
El enfoque que se muestra a continuación se puede aplicar a todas las solicitudes de ajax listas para usar (si obviamente no se redefinen antes del evento Enviar).
Antes de realizar cualquier solicitud ajax
CheckPulse
, se invoca el método (el método del controlador, que puede ser cualquier cosa más simple):Si el usuario no está autenticado (el token ha caducado), no se puede acceder a dicho método (protegido por
Authorize
atributo). Debido a que el marco maneja la autenticación, mientras que el token expira, pone el estado http 302 a la respuesta. Si no desea que su navegador maneje la respuesta 302 de manera transparente, póngala en Global.asax y cambie el estado de la respuesta, por ejemplo, a 200 OK. Además, agregue el encabezado, que le indica que procese dicha respuesta de manera especial (más adelante en el lado del cliente):Finalmente, en el lado del cliente, verifique ese encabezado personalizado. Si está presente, se debe realizar una redirección completa a la página de inicio de sesión (en mi caso,
window.location
se reemplaza por la url de la solicitud, que mi marco maneja automáticamente).fuente
Creo que una mejor manera de manejar esto es aprovechar los códigos de respuesta del protocolo HTTP existentes, específicamente
401 Unauthorized
.Así es como lo resolví:
Lado del cliente: enlace a los eventos ajax
OMI, esto es más genérico y no está escribiendo algunas nuevas especificaciones / encabezados personalizados. Tampoco debería tener que modificar ninguna de sus llamadas ajax existentes.
Editar: según el comentario de @ Rob a continuación, 401 (el código de estado HTTP para errores de autenticación) debería ser el indicador. Consulte 403 Prohibido vs 401 Respuestas HTTP no autorizadas para más detalles. Dicho esto, algunos marcos web usan 403 tanto para errores de autenticación como de autorización, por lo que debe adaptarse en consecuencia. Gracias Rob
fuente
Resolví este problema así:
Agregue un middleware para procesar la respuesta, si es una redirección para una solicitud ajax, cambie la respuesta a una respuesta normal con la URL de redireccionamiento.
Luego, en ajaxComplete, si la respuesta contiene redirección, debe ser una redirección, por lo tanto, cambie la ubicación del navegador.
fuente
Tengo una solución simple que funciona para mí, no es necesario cambiar el código del servidor ... solo agregue una cucharadita de nuez moscada ...
Verifico la presencia de la etiqueta html, pero puede cambiar el indexOf para buscar cualquier cadena única que exista en su página de inicio de sesión ...
fuente
Otra solución que encontré (especialmente útil si desea establecer un comportamiento global) es utilizar el
$.ajaxsetup()
método junto con lastatusCode
propiedad . Como otros señalaron, no use un código de estado de redireccionamiento (3xx
), en su lugar use un4xx
código de estado y maneje el lado del cliente de redireccionamiento.Reemplace
400
con el código de estado que desea manejar. Como ya se mencionó401 Unauthorized
podría ser una buena idea. Lo uso400
ya que es muy inespecífico y puedo usarlo401
para casos más específicos (como credenciales de inicio de sesión incorrectas). Entonces, en lugar de redirigir directamente, su backend debería devolver un4xx
código de error cuando la sesión expiró y usted maneja la redirección del lado del cliente. Funciona perfecto para mí incluso con frameworks como backbone.jsfuente
La mayoría de las soluciones dadas usan una solución alternativa, usando un encabezado adicional o un código HTTP inapropiado. Es probable que esas soluciones funcionen, pero se sienten un poco 'hacky'. Se me ocurrió otra solución.
Estamos utilizando WIF que está configurado para redirigir (passiveRedirectEnabled = "true") en una respuesta 401. La redirección es útil cuando se manejan solicitudes normales, pero no funcionará para solicitudes AJAX (ya que los navegadores no ejecutarán el 302 / redirect).
Usando el siguiente código en su global.asax puede deshabilitar la redirección para solicitudes AJAX:
Esto le permite devolver 401 respuestas para solicitudes AJAX, que su javascript puede manejar volviendo a cargar la página. Recargar la página arrojará un 401 que será manejado por WIF (y WIF redirigirá al usuario a la página de inicio de sesión).
Un ejemplo de JavaScript para manejar errores 401:
fuente
Este problema puede aparecer usando el método ASP.NET MVC RedirectToAction. Para evitar que el formulario muestre la respuesta en div, simplemente puede hacer algún tipo de filtro de respuesta ajax para las respuestas entrantes con $ .ajaxSetup . Si la respuesta contiene redirección MVC, puede evaluar esta expresión en el lado JS. Código de ejemplo para JS a continuación:
Si los datos son: "window.location = '/ Acount / Login'", el filtro anterior capturará eso y evaluará la redirección en lugar de permitir que se muestren los datos.
fuente
data
está en el cuerpo de respuesta o encabezado?Reuniendo lo que dijeron Vladimir Prudnikov y Thomas Hansen:
Esto hace que el navegador trate la respuesta como un éxito y la entregue a su Javascript.
fuente
fuente
Tratar
Ponlo en la página de inicio de sesión. Si se cargó en un div en la página principal, se redirigirá hasta la página de inicio de sesión. "#site" es una identificación de un div que se encuentra en todas las páginas, excepto en la página de inicio de sesión.
fuente
Si bien las respuestas parecen funcionar para las personas si está usando Spring Security, he encontrado que extender LoginUrlAuthenticationEntryPoint y agregar código específico para manejar AJAX es más robusto. La mayoría de los ejemplos interceptan todos los redireccionamientos, no solo las fallas de autenticación. Esto no fue deseable para el proyecto en el que trabajo. Es posible que también necesite ampliar ExceptionTranslationFilter y anular el método "sendStartAuthentication" para eliminar el paso de almacenamiento en caché si no desea que la solicitud AJAX fallida se almacene en caché.
Ejemplo AjaxAwareAuthenticationEntryPoint:
Fuentes: 1 , 2
fuente
Resolví esto poniendo lo siguiente en mi página login.php.
fuente
Permítanme citar nuevamente el problema como lo describe @Steg
En mi humilde opinión, este es un verdadero desafío y tendrá que extenderse oficialmente a los estándares HTTP actuales.
Creo que el nuevo estándar Http será utilizar un nuevo código de estado. significado: actualmente
301/302
le dice al navegador que vaya y busque el contenido de esta solicitud a uno nuevolocation
.En el estándar extendido, dirá que si la respuesta
status: 308
(solo un ejemplo), el navegador debe redirigir la página principal alocation
proporcionada.Habiendo dicho eso; Me inclino a imitar este comportamiento futuro y, por lo tanto, cuando se necesita un document.redirect, hago que el servidor responda como:
Cuando JS obtiene el "
status: 204
", comprueba la existencia delx-status: 308
encabezado y realiza un document.redirect a la página proporcionada en ellocation
encabezado.¿Esto tiene algún sentido para usted?
fuente
Algunos pueden encontrar útil lo siguiente:
Quería que los clientes fueran redirigidos a la página de inicio de sesión para cualquier acción de descanso que se envíe sin un token de autorización. Dado que todas mis acciones de descanso están basadas en Ajax, necesitaba una buena forma genérica para redirigir a la página de inicio de sesión en lugar de manejar la función de éxito de Ajax.
Esto es lo que he hecho:
En cualquier solicitud de Ajax, mi servidor devolverá una respuesta Json 200 "NECESITA AUTENTICARSE" (si el cliente necesita autenticarse).
Ejemplo simple en Java (lado del servidor):
En mi Javascript he agregado el siguiente código:
Y eso es todo.
fuente
en el servlet deberías poner
response.setStatus(response.SC_MOVED_PERMANENTLY);
para enviar el estado '301' xmlHttp que necesita para una redirección ...y en la función $ .ajax no deberías usar la
.toString()
función ..., soloif (xmlHttp.status == 301) { top.location.href = 'xxxx.jsp'; }
el problema es que no es muy flexible, no puedes decidir hacia dónde quieres redirigir ...
redireccionar a través de los servlets debería ser la mejor manera. pero todavía no puedo encontrar la manera correcta de hacerlo.
fuente
Solo quería conectarme a cualquier solicitud de ajax para toda la página. @SuperG me ayudó a comenzar. Esto es lo que terminé con:
Quería verificar específicamente ciertos códigos de estado http para basar mi decisión. Sin embargo, puedes unirte a ajaxError para obtener algo más que éxito (¿200 solo quizás?) Podría haber escrito:
fuente
Si también desea pasar los valores, también puede establecer las variables de sesión y acceder, por ejemplo: en su jsp puede escribir
Y luego puede almacenar este valor temporal en su variable de JavaScript y jugar
fuente
No tuve éxito con la solución de encabezado: nunca se recogieron en mi método ajaxSuccess / ajaxComplete. Usé la respuesta de Steg con la respuesta personalizada, pero modifiqué un poco el lado JS. Configuré un método al que llamo en cada función para poder usar el estándar
$.get
y los$.post
métodos.Ejemplo de uso ...
fuente
Finalmente, resuelvo el problema agregando una costumbre
HTTP Header
. Justo antes de la respuesta para cada solicitud en el lado del servidor, agrego la URL solicitada actual al encabezado de la respuesta.Mi tipo de aplicación en el servidor es
Asp.Net MVC
, y tiene un buen lugar para hacerlo. enGlobal.asax
implementado elApplication_EndRequest
evento así:¡Funciona perfecto para mí! Ahora, en cada respuesta de
JQuery
$.post
i, tengo losurl
encabezados de respuesta solicitados y también otros que vienen como resultado delPOST
método por estado302
,303
, ....y otra cosa importante es que no hay necesidad de modificar el código del lado del servidor ni del lado del cliente.
y el siguiente es la capacidad de obtener acceso a la otra información de la acción posterior, tales errores, mensajes y ..., de esta manera.
Publiqué esto, tal vez ayudar a alguien :)
fuente
Estaba teniendo este problema en una aplicación de django con la que estoy jugando (descargo de responsabilidad: estoy jugando para aprender, y de ninguna manera soy un experto). Lo que quería hacer era usar jQuery ajax para enviar una solicitud DELETE a un recurso, eliminarla en el lado del servidor y luego enviar una redirección a (básicamente) la página de inicio. Cuando envié
HttpResponseRedirect('/the-redirect/')
desde el script de Python, el método ajax de jQuery estaba recibiendo 200 en lugar de 302. Entonces, lo que hice fue enviar una respuesta de 300 con:Luego envié / manejé la solicitud en el cliente con jQuery.ajax así:
Quizás usar 300 no sea "correcto", pero al menos funcionó tal como yo quería.
PD: esto fue un gran dolor para editar en la versión móvil de SO. ¡El estúpido ISP envió mi solicitud de cancelación de servicio justo cuando terminé con mi respuesta!
fuente
También puede conectar el prototipo de envío XMLHttpRequest. Esto funcionará para todos los envíos (jQuery / dojo / etc) con un controlador.
Escribí este código para manejar un error de 500 páginas caducadas, pero debería funcionar igual de bien para atrapar una redirección de 200. Prepare la entrada de wikipedia en XMLHttpRequest onreadystatechange sobre el significado de readyState.
fuente
Además, es probable que desee redirigir al usuario a la URL dada en los encabezados. Así que finalmente se verá así:
UPD: Opps. Tiene la misma tarea, pero no funciona. Haciendo esto Te mostraré la solución cuando la encuentre.
fuente
Obtuve una solución funcional usando las respuestas de @John y @Arpad link y @RobWinch link
Yo uso Spring Security 3.2.9 y jQuery 1.10.2.
Extienda la clase de Spring para causar una respuesta 4XX solo de solicitudes AJAX:
applicationContext-security.xml
En mis JSP, agregue un controlador de errores AJAX global como se muestra aquí
Además, elimine los controladores de errores existentes de las llamadas AJAX en las páginas JSP:
Espero que ayude a los demás.
Actualización1 Descubrí que necesitaba agregar la opción (always-use-default-target = "true") a la configuración de inicio de sesión de formulario. Esto era necesario ya que después de que una solicitud AJAX se redirige a la página de inicio de sesión (debido a una sesión expirada), Spring recuerda la solicitud AJAX anterior y se redirige automáticamente después de iniciar sesión. Esto hace que el JSON devuelto se muestre en la página del navegador. Por supuesto, no es lo que quiero.
Actualización2 En lugar de usar
always-use-default-target="true"
, use el ejemplo @RobWinch de bloquear solicitudes AJAX de requstCache. Esto permite que los enlaces normales se redirijan a su destino original después de iniciar sesión, pero AJAX va a la página de inicio después de iniciar sesión.fuente