variable redireccionar por pasar formulario example enviar ejemplos con javascript jquery ajax redirect

javascript - redireccionar - Cómo gestionar una solicitud de redireccionamiento después de una llamada jQuery Ajax



pasar variable de javascript a php por ajax (30)

Algunos pueden encontrar lo siguiente útil:

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. Como 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 "NECESIDAD DE AUTENTICAR" (si el cliente necesita autenticarse).

Ejemplo simple en Java (lado del servidor):

@Secured @Provider @Priority(Priorities.AUTHENTICATION) public class AuthenticationFilter implements ContainerRequestFilter { private final Logger m_logger = LoggerFactory.getLogger(AuthenticationFilter.class); public static final String COOKIE_NAME = "token_cookie"; @Override public void filter(ContainerRequestContext context) throws IOException { // Check if it has a cookie. try { Map<String, Cookie> cookies = context.getCookies(); if (!cookies.containsKey(COOKIE_NAME)) { m_logger.debug("No cookie set - redirect to login page"); throw new AuthenticationException(); } } catch (AuthenticationException e) { context.abortWith(Response.ok("/"NEED TO AUTHENTICATE/"").type("json/application").build()); } } }

En mi Javascript he añadido el siguiente código:

$.ajaxPrefilter(function(options, originalOptions, jqXHR) { var originalSuccess = options.success; options.success = function(data) { if (data == "NEED TO AUTHENTICATE") { window.location.replace("/login.html"); } else { originalSuccess(data); } }; });

Y eso es todo.

Estoy usando $.post() para llamar a un servlet usando Ajax y luego usar el fragmento HTML resultante para reemplazar un elemento div en la página actual del usuario. Sin embargo, si la sesión se agota, 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 el elemento div 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?


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í:

  1. Lado del servidor: si la sesión expira, y la solicitud es ajax. enviar un encabezado de código de respuesta 401
  2. Lado del cliente: Enlazar a los eventos ajax.

    $(''body'').bind(''ajaxSuccess'',function(event,request,settings){ if (401 == request.status){ window.location = ''/users/login''; } }).bind(''ajaxError'',function(event,request,settings){ if (401 == request.status){ window.location = ''/users/login''; } });

En mi opinión, 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.

Edición: el comentario de Per @ Rob a continuación, 401 (el código de estado HTTP para los errores de autenticación) debe ser el indicador. Consulte 403 Respuestas HTTP no autorizadas vs 401 respuestas no autorizadas para obtener más detalles. Dicho esto, algunos marcos web utilizan 403 tanto para errores de autenticación como de autorización, así que adáptelos. Gracias rob


Este problema puede aparecer luego utilizando el método de redireccionamiento de ASP.NET MVC. Para evitar que el formulario muestre la respuesta en div, simplemente puede hacer algún tipo de filtro de respuesta ajax para incluir las respuestas con $ .ajaxSetup . Si la respuesta contiene redireccionamiento MVC, puede evaluar esta expresión en el lado JS. Código de ejemplo para JS a continuación:

$.ajaxSetup({ dataFilter: function (data, type) { if (data && typeof data == "string") { if (data.indexOf(''window.location'') > -1) { eval(data); } } return data; } });

Si los datos son: "window.location = ''/ Acount / Login''", el filtro anterior lo detectará y evaluará para hacer la redirección en lugar de permitir que se muestren los datos.


La mayoría de las soluciones proporcionadas utilizan una solución alternativa, utilizando un encabezado adicional o un código HTTP inadecuado. Esas soluciones probablemente funcionarán, pero se sentirán un poco ''hacky''. Se me ha ocurrido otra solución.

Estamos usando WIF que está configurado para redirigir (passiveRedirectEnabled = "true") en una respuesta 401. La redirección es útil cuando se manejan solicitudes normales pero no funciona 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:

void WSFederationAuthenticationModule_AuthorizationFailed(object sender, AuthorizationFailedEventArgs e) { string requestedWithHeader = HttpContext.Current.Request.Headers["X-Requested-With"]; if (!string.IsNullOrEmpty(requestedWithHeader) && requestedWithHeader.Equals("XMLHttpRequest", StringComparison.OrdinalIgnoreCase)) { e.RedirectToIdentityProvider = false; } }

Esto le permite devolver 401 respuestas para solicitudes AJAX, que su javascript puede manejar al recargar la página. La recarga de 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 401 errores:

$(document).ajaxError(function (event, jqxhr, settings, exception) { if (jqxhr.status == 401) { //Forbidden, go to login //Use a reload, WIF will redirect to Login location.reload(true); } });


La solución que finalmente se implementó fue usar un envoltorio para la función de devolución de llamada de la llamada Ajax y, en este envoltorio, verificar la existencia de un elemento específico en el fragmento HTML devuelto. Si se encontró el elemento, la envoltura ejecutó una redirección. De lo contrario, el reiniciador reenvía la llamada a la función de devolución de llamada real.

Por ejemplo, nuestra función de envoltura era algo así como:

function cbWrapper(data, funct){ if($("#myForm", data).length > 0) top.location.href="login.htm";//redirection else funct(data); }

Luego, al hacer la llamada Ajax usamos algo como:

$.post("myAjaxHandler", { param1: foo, param2: bar }, function(data){ cbWrapper(data, myActualCB); }, "html" );

Esto funcionó para nosotros porque todas las llamadas 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.


Leí esta pregunta e implementé el enfoque que se ha establecido con respecto a establecer el código de estado de respuesta en 278 para evitar que el navegador maneje de forma transparente las redirecciones. A pesar de que esto funcionó, estaba un poco insatisfecho ya que es un poco pirateado.

Después de investigar más, abandoné este enfoque y usé JSON . En este caso, todas las respuestas a las solicitudes de 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é debe 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 ve algo como:

$.ajax({ type: "POST", url: reqUrl, data: reqBody, dataType: "json", success: function(data, textStatus) { if (data.redirect) { // data.redirect contains the string URL to redirect to window.location.href = data.redirect; } else { // data.form contains the HTML for the replacement form $("#myform").replaceWith(data.form); } } });

El objeto JSON "datos" se construye en el servidor para tener 2 miembros: data.redirect y data.form. Encontré este enfoque para ser mucho mejor.


Me gusta el método de Timmerz con un ligero toque de limón. Si alguna vez le devuelven contentType of text / html cuando espera JSON , lo más probable es que lo redirijan. En mi caso, simplemente recargo la página, y se redirige a la página de inicio de sesión. Ah, y verifica que el estado de jqXHR sea 200, lo que parece una tontería, porque estás en la función de error, ¿verdad? De lo contrario, los casos de error legítimos forzarán una recarga iterativa (oops)

$.ajax( error: function (jqXHR, timeout, message) { var contentType = jqXHR.getResponseHeader("Content-Type"); if (jqXHR.status === 200 && contentType.toLowerCase().indexOf("text/html") >= 0) { // assume that our login has expired - reload our current page window.location.reload(); } });


Ningún navegador maneja 301 y 302 respuestas correctamente. Y, de hecho, el estándar incluso dice que deben manejarlos "de manera transparente", que es un dolor de cabeza MASIVO para los proveedores de la Biblioteca Ajax. En Ra-Ajax nos obligaron 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, le agradecería que le dijera al W3C que realmente necesitamos manejar los códigos 301 y 302 por nosotros mismos ...! ;)


Otra solución que encontré (especialmente útil si desea establecer un comportamiento global) es usar el $.ajaxsetup() junto con la propiedad statusCode . Como señalan otros, no use un código de estado de redireccionamiento ( 3xx ), en su lugar use un código de estado 4xx y maneje el lado del cliente de redireccionamiento.

$.ajaxSetup({ statusCode : { 400 : function () { window.location = "/"; } } });

Reemplace 400 con el código de estado que desea manejar. Como ya se mencionó 401 Unauthorized podría ser una buena idea. Utilizo el 400 ya que es muy poco específico y puedo usar el 401 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 un código de error 4xx cuando se agote el tiempo de espera y usted maneje el lado del cliente que redirige. Funciona perfecto para mí incluso con marcos como backbone.js


Permítanme citar nuevamente el problema como lo describe @Steg

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.

En mi humilde opinión, esto es un verdadero desafío y tendrá que extenderse oficialmente a los estándares HTTP actuales.

Creo que el nuevo estándar HTTP será usar un nuevo código de estado. es decir, actualmente 301/302 le dice al navegador que vaya a buscar el contenido de esta solicitud a una nueva location .

En el estándar extendido, dirá que si el status: 308 respuesta es status: 308 (solo un ejemplo), el navegador debe redirigir la página principal a la location provista.

Habiendo dicho eso; Me inclino a imitar este comportamiento futuro y, por lo tanto, cuando se necesita document.redirect, el servidor responde como:

status: 204 No Content x-status: 308 Document Redirect x-location: /login.html

Cuando JS obtiene el " status: 204 ", verifica la existencia del encabezado x-status: 308 y realiza una redirección de documentos a la página provista en el encabezado de la location .

¿Esto tiene algún sentido para usted?


Resolví este problema así:

Agregue un middleware para procesar la respuesta, si es un redireccionamiento para una solicitud ajax, cambie la respuesta a una respuesta normal con la URL de redireccionamiento.

class AjaxRedirect(object): def process_response(self, request, response): if request.is_ajax(): if type(response) == HttpResponseRedirect: r = HttpResponse(json.dumps({''redirect'': response[''Location'']})) return r return response

Luego, en ajaxComplete, si la respuesta contiene una redirección, debe ser una redirección, así que cambie la ubicación del navegador.

$(''body'').ajaxComplete(function (e, xhr, settings) { if (xhr.status == 200) { var redirect = null; try { redirect = $.parseJSON(xhr.responseText).redirect; if (redirect) { window.location.href = redirect.replace(//?.*$/, "?next=" + window.location.pathname); } } catch (e) { return; } } }


Resolví este problema por:

  1. Añadiendo un encabezado personalizado a la respuesta:

    public ActionResult Index(){ if (!HttpContext.User.Identity.IsAuthenticated) { HttpContext.Response.AddHeader("REQUIRES_AUTH","1"); } return View(); }

  2. Enlazar una función de JavaScript al evento ajaxSuccess y verificar si existe el encabezado:

    $(document).ajaxSuccess(function(event, request, settings) { if (request.getResponseHeader(''REQUIRES_AUTH'') === ''1'') { window.location = ''/''; } });


Resolví esto poniendo lo siguiente en mi página login.php.

<script type="text/javascript"> if (top.location.href.indexOf(''login.php'') == -1) { top.location.href = ''/login.php''; } </script>


Reuniendo lo que Vladimir Prudnikov y Thomas Hansen dijeron:

  • Cambie su código del lado del servidor para detectar si es un XHR. Si es así, establezca el código de respuesta de la redirección a 278. En django:

if request.is_ajax(): response.status_code = 278

Esto hace que el navegador trate la respuesta como un éxito y se la entregue a su Javascript.

  • En su JS, asegúrese de que el envío del formulario sea a través de Ajax, verifique el código de respuesta y redirija si es necesario:

$(''#my-form'').submit(function(event){ event.preventDefault(); var options = { url: $(this).attr(''action''), type: ''POST'', complete: function(response, textStatus) { if (response.status == 278) { window.location = response.getResponseHeader(''Location'') } else { ... your code here ... } }, data: $(this).serialize(), }; $.ajax(options); });


Sé que este tema es antiguo, pero daré otro enfoque que he encontrado y descrito anteriormente here . Básicamente, estoy usando ASP.MVC con WIF (pero esto no es realmente importante para el contexto de este tema: la respuesta es adecuada, independientemente de los marcos que se usen. La pista se mantiene sin cambios: se trata de 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 fuera de la caja (si no se redefinen antes del evento de Envío, obviamente).

$.ajaxSetup({ beforeSend: checkPulse, error: function (XMLHttpRequest, textStatus, errorThrown) { document.open(); document.write(XMLHttpRequest.responseText); document.close(); } });

Antes de realizar cualquier solicitud ajax, se CheckPulse método CheckPulse (el método del controlador, que puede ser cualquier cosa más simple):

[Authorize] public virtual void CheckPulse() {}

Si el usuario no está autenticado (el token ha caducado), no se puede acceder a dicho método (protegido por el atributo Authorize ). Debido a que el marco maneja la autenticación, mientras el token caduca, coloca el estado http 302 en la respuesta. Si no desea que su navegador maneje la respuesta 302 de forma transparente, cójalo 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):

protected void Application_EndRequest() { if (Context.Response.StatusCode == 302 && (new HttpContextWrapper(Context)).Request.IsAjaxRequest()) { Context.Response.StatusCode = 200; Context.Response.AddHeader("REQUIRES_AUTH", "1"); } }

Por último, en el lado del cliente compruebe tal encabezado personalizado. Si es actual, se debe realizar la redirección completa a la página de inicio de sesión (en mi caso, window.location se reemplaza por url desde la solicitud, que se maneja automáticamente por mi marco).

function checkPulse(XMLHttpRequest) { var location = window.location.href; $.ajax({ url: "/Controller/CheckPulse", type: ''GET'', async: false, beforeSend: null, success: function (result, textStatus, xhr) { if (xhr.getResponseHeader(''REQUIRES_AUTH'') === ''1'') { XMLHttpRequest.abort(); // terminate further ajax execution window.location = location; } } }); }


Si bien las respuestas parecen funcionar para las personas, si está utilizando Spring Security, he encontrado que extender LoginUrlAuthenticationEntryPoint y agregar un código específico para manejar AJAX es más sólido. La mayoría de los ejemplos interceptan todas las redirecciones, no solo las fallas de autenticación. Esto fue indeseable para el proyecto en el que trabajo. Puede encontrar la necesidad de extender ExceptionTranslationFilter y anular el método "sendStartAuthentication" para eliminar el paso de almacenamiento en caché si no desea que la solicitud AJAX fallida esté en caché.

Ejemplo AjaxAwareAuthenticationEntryPoint:

public class AjaxAwareAuthenticationEntryPoint extends LoginUrlAuthenticationEntryPoint { public AjaxAwareAuthenticationEntryPoint(String loginUrl) { super(loginUrl); } @Override public void commence(HttpServletRequest request, HttpServletResponse response, AuthenticationException authException) throws IOException, ServletException { if (isAjax(request)) { response.sendError(HttpStatus.UNAUTHORIZED.value(), "Please re-authenticate yourself"); } else { super.commence(request, response, authException); } } public static boolean isAjax(HttpServletRequest request) { return request != null && "XMLHttpRequest".equals(request.getHeader("X-Requested-With")); } }

Fuentes: 1 , 2


Solo quería aferrarme a cualquier solicitud de ajax para toda la página. @SuperG me hizo empezar. Esto es lo que terminé con:

// redirect ajax requests that are redirected, not found (404), or forbidden (403.) $(''body'').bind(''ajaxComplete'', function(event,request,settings){ switch(request.status) { case 301: case 404: case 403: window.location.replace("http://mysite.tld/login"); break; } });

Quería verificar específicamente ciertos códigos de estado http para basar mi decisión en. Sin embargo, solo puedes unirte a ajaxError para obtener algo que no sea el éxito (¿200 solo quizás?) Podría haber escrito:

$(''body'').bind(''ajaxError'', function(event,request,settings){ window.location.replace("http://mysite.tld/login"); }


Solo quería compartir mi enfoque ya que esto podría ayudar a alguien:

Básicamente, incluí un módulo JavaScript que maneja las cosas de autenticación como mostrar el nombre de usuario y también este caso que maneja 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 en nuestra página de inicio de sesión.

En mi módulo de JavaScript mi enfoque inicial fue algo así como

$(document).ajaxComplete(function(e, xhr, settings){ if(xhr.status === 302){ //check for location header and redirect... } });

El problema (como muchos de los que ya ajaxComplete mencionado) es que el navegador maneja el redireccionamiento por sí mismo, por lo que mi llamada ajaxComplete nunca fue llamada, pero en cambio obtuve la respuesta de la página de inicio de sesión ya redirigida que obviamente era un status 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 302 respuestas de redirección, agregué un encabezado LoginPage 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:

if(xhr.status === 200){ var loginPageRedirectHeader = xhr.getResponseHeader("LoginPage"); if(loginPageRedirectHeader && loginPageRedirectHeader !== ""){ window.location.replace(loginPageRedirectHeader); } }

... y eso funciona a la perfección :). Quizás se pregunte por qué LoginPage la url en el encabezado de LoginPage ... bueno, básicamente porque no encontré la manera de determinar la url de GET resultante del redireccionamiento automático de la ubicación desde el objeto xhr ...


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 ...

$(document).ready(function () { $(document).ajaxSend( function(event,request,settings) { var intercepted_success = settings.success; settings.success = function( a, b, c ) { if( request.responseText.indexOf( "<html>" ) > -1 ) window.location = window.location; else intercepted_success( a, b, c ); }; }); });

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 ...


Tratar

$(document).ready(function () { if ($("#site").length > 0) { window.location = "<%= Url.Content("~") %>" + "Login/LogOn"; } });

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 un id de un div que se encuentra en todas las páginas excepto en la página de inicio de sesión.


Utilice la llamada $.ajax() bajo nivel:

$.ajax({ url: "/yourservlet", data: { }, complete: function(xmlHttp) { // xmlHttp is a XMLHttpRquest object alert(xmlHttp.status); } });

Intenta esto para una redirección:

if (xmlHttp.code != 200) { top.location.href = ''/some/other/page''; }


en el servlet debes poner response.setStatus(response.SC_MOVED_PERMANENTLY); para enviar el estado xmlHttp ''301'' que necesita para una redirección ...

y en la función $ .ajax no debería usar la función .toString() ..., solo

if (xmlHttp.status == 301) { top.location.href = ''xxxx.jsp''; }

El problema es que no es muy flexible, no puede decidir dónde desea redirigir ...

La redirección a través de los servlets debería ser la mejor manera. Pero todavía no puedo encontrar la manera correcta de hacerlo.


Si también quiere pasar los valores, también puede configurar las variables de sesión y acceder, por ejemplo, en su jsp puede escribir

<% HttpSession ses = request.getSession(true); String temp=request.getAttribute("what_you_defined"); %>

Y luego puedes almacenar este valor temporal en tu variable javascript y jugar.


Además, probablemente querrá redirigir al usuario a la URL que figura en los encabezados. Así que finalmente se verá así:

$.ajax({ //.... other definition complete:function(xmlHttp){ if(xmlHttp.status.toString()[0]==''3''){ top.location.href = xmlHttp.getResponseHeader(''Location''); } });

UPD: Opps. Tienen la misma tarea, pero no funciona. Haciendo estas cosas Te mostraré la solución cuando la encuentre.


Estaba teniendo este problema en una aplicación de django con la que estoy haciendo pequeños retoques (descargo de responsabilidad: estoy tratando de 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 del 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 recibía 200 en lugar de 302. Entonces, lo que hice fue enviar una respuesta de 300 con:

response = HttpResponse(status=''300'') response[''Location''] = ''/the-redirect/'' return response

Luego envié / manejé la solicitud en el cliente con jQuery.ajax así:

<button onclick="*the-jquery*">Delete</button> where *the-jquery* = $.ajax({ type: ''DELETE'', url: ''/resource-url/'', complete: function(jqxhr){ window.location = jqxhr.getResponseHeader(''Location''); } });

Tal vez el uso de 300 no es "correcto", pero al menos funcionó como yo quería.

PD: este fue un gran problema para editar en la versión móvil de SO. ¡El ISP estúpido puso mi solicitud de cancelación de servicio justo cuando terminé con mi respuesta!


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. En lo Global.asaximplementé el Application_EndRequestevento así:

public class MvcApplication : System.Web.HttpApplication { // ... // ... protected void Application_EndRequest(object sender, EventArgs e) { var app = (HttpApplication)sender; app.Context.Response.Headers.Add("CurrentUrl",app.Context. Request.CurrentExecutionFilePath); } }

¡Funciona perfecto para mí! Ahora en cada respuesta de la JQuery $.postque he solicitado el urly también otras cabeceras de respuesta que viene como resultado de POSTmétodo por el estado 302, 303, ....

y otra cosa importante es que no es necesario modificar el código del lado del servidor ni del lado del cliente.

y la siguiente es la capacidad de obtener acceso a la otra información de la acción posterior, tales como errores, mensajes y ..., de esta manera.

Publiqué esto, tal vez ayude a alguien :)


No tuve ningún éxito con la solución de encabezado; nunca fueron recogidos 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 métodos $.gety $.postmétodos estándar .

function handleAjaxResponse(data, callback) { //Try to convert and parse object try { if (jQuery.type(data) === "string") { data = jQuery.parseJSON(data); } if (data.error) { if (data.error == ''login'') { window.location.reload(); return; } else if (data.error.length > 0) { alert(data.error); return; } } } catch(ex) { } if (callback) { callback(data); } }

Ejemplo de ello en uso ...

function submitAjaxForm(form, url, action) { //Lock form form.find(''.ajax-submit'').hide(); form.find(''.loader'').show(); $.post(url, form.serialize(), function (d) { //Unlock form form.find(''.ajax-submit'').show(); form.find(''.loader'').hide(); handleAjaxResponse(d, function (data) { // ... more code for if auth passes ... }); }); return false; }


Obtuve una solución de trabajo utilizando las respuestas de @John y @Arpad .com/a/8426947/4505142 y @RobWinch link

Yo uso Spring Security 3.2.9 y jQuery 1.10.2.

Extienda la clase de Spring para provocar la respuesta 4XX solo de las solicitudes AJAX:

public class CustomLoginUrlAuthenticationEntryPoint extends LoginUrlAuthenticationEntryPoint { public CustomLoginUrlAuthenticationEntryPoint(final String loginFormUrl) { super(loginFormUrl); } // For AJAX requests for user that isn''t logged in, need to return 403 status. // For normal requests, Spring does a (302) redirect to login.jsp which the browser handles normally. @Override public void commence(final HttpServletRequest request, final HttpServletResponse response, final AuthenticationException authException) throws IOException, ServletException { if ("XMLHttpRequest".equals(request.getHeader("X-Requested-With"))) { response.sendError(HttpServletResponse.SC_FORBIDDEN, "Access Denied"); } else { super.commence(request, response, authException); } } }

applicationContext-security.xml

<security:http auto-config="false" use-expressions="true" entry-point-ref="customAuthEntryPoint" > <security:form-login login-page=''/login.jsp'' default-target-url=''/index.jsp'' authentication-failure-url="/login.jsp?error=true" /> <security:access-denied-handler error-page="/errorPage.jsp"/> <security:logout logout-success-url="/login.jsp?logout" /> ... <bean id="customAuthEntryPoint" class="com.myapp.utils.CustomLoginUrlAuthenticationEntryPoint" scope="singleton"> <constructor-arg value="/login.jsp" /> </bean> ... <bean id="requestCache" class="org.springframework.security.web.savedrequest.HttpSessionRequestCache"> <property name="requestMatcher"> <bean class="org.springframework.security.web.util.matcher.NegatedRequestMatcher"> <constructor-arg> <bean class="org.springframework.security.web.util.matcher.MediaTypeRequestMatcher"> <constructor-arg> <bean class="org.springframework.web.accept.HeaderContentNegotiationStrategy"/> </constructor-arg> <constructor-arg value="#{T(org.springframework.http.MediaType).APPLICATION_JSON}"/> <property name="useEquals" value="true"/> </bean> </constructor-arg> </bean> </property> </bean>

En mis JSP, agregue un controlador de errores AJAX global como se muestra here

$( document ).ajaxError(function( event, jqxhr, settings, thrownError ) { if ( jqxhr.status === 403 ) { window.location = "login.jsp"; } else { if(thrownError != null) { alert(thrownError); } else { alert("error"); } } });

Además, elimine los manejadores de errores existentes de las llamadas AJAX en las páginas JSP:

var str = $("#viewForm").serialize(); $.ajax({ url: "get_mongoDB_doc_versions.do", type: "post", data: str, cache: false, async: false, dataType: "json", success: function(data) { ... }, // error: function (jqXHR, textStatus, errorStr) { // if(textStatus != null) // alert(textStatus); // else if(errorStr != null) // alert(errorStr); // else // alert("error"); // } });

Espero que ayude a los demás.

Update1 Encontré que necesitaba agregar la opción (always-use-default-target = "true") a la configuración de inicio de sesión de formulario. Esto fue necesario ya que después de que una solicitud de AJAX se redirige a la página de inicio de sesión (debido a una sesión vencida), Spring recuerda la solicitud de AJAX anterior y la redirige automáticamente a ella 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.

Update2 En lugar de usar always-use-default-target="true", use el ejemplo @RobWinch del bloqueo de solicitudes AJAX desde el 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.


También puede enlazar 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 un redireccionamiento de 200. Prepare la entrada de wikipedia en XMLHttpRequest onreadystatechange sobre el significado de readyState.

// Hook XMLHttpRequest var oldXMLHttpRequestSend = XMLHttpRequest.prototype.send; XMLHttpRequest.prototype.send = function() { //console.dir( this ); this.onreadystatechange = function() { if (this.readyState == 4 && this.status == 500 && this.responseText.indexOf("Expired") != -1) { try { document.documentElement.innerHTML = this.responseText; } catch(error) { // IE makes document.documentElement read only document.body.innerHTML = this.responseText; } } }; oldXMLHttpRequestSend.apply(this, arguments); }


<script> function showValues() { var str = $("form").serialize(); $.post(''loginUser.html'', str, function(responseText, responseStatus, responseXML){ if(responseStatus=="success"){ window.location= "adminIndex.html"; } }); } </script>