我使用$.post()使用Ajax调用servlet,然后使用生成的HTML片段替换用户当前页面中的div元素。但是,如果会话超时,服务器将发送重定向指令,将用户发送到登录页面。在本例中,jQuery用登录页面的内容替换div元素,迫使用户的眼睛看到一个罕见的场景。

如何使用jQuery1.2.6管理Ajax调用的重定向指令?


当前回答

把弗拉基米尔·普拉德尼科夫和托马斯·汉森所说的话放在一起:

更改服务器端代码以检测它是否是XHR。如果是,则将重定向的响应代码设置为278。在django:

如果request.is_ajax():响应状态代码=278

这使得浏览器将响应视为成功,并将其交给您的Javascript。

在JS中,确保通过Ajax提交表单,检查响应代码并根据需要重定向:

$(“#my form”).submit(函数(事件){event.prpreventDefault();var选项={url:$(this).attr('action'),类型:'POST',complete:函数(响应,textStatus){如果(response.status==278){window.location=响应.getResponseHeader(“位置”)}否则{…您的代码在这里…}},data:$(this).serialize(),}; $.ajax(选项);});

其他回答

我在一个我正在修补的django应用程序上遇到了这个问题(免责声明:我正在修补以学习,绝不是专家)。我想做的是使用jQueryajax向资源发送DELETE请求,在服务器端删除它,然后(基本上)将重定向返回主页。当我从python脚本发送HttpResponseRedirect('/theRedirect/')时,jQuery的ajax方法收到的是200而不是302。因此,我所做的是发送一个300的回复,其中包括:

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

然后,我使用jQuery.ajax在客户端上发送/处理请求,如下所示:

<button onclick="*the-jquery*">Delete</button>

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

也许使用300并不“正确”,但至少它的工作方式和我想的一样。

PS:这是一个巨大的痛苦,在移动版SO上编辑。愚蠢的ISP在我完成我的回答后,立即通过了我的服务取消请求!

我通过以下方式解决了这个问题:

向响应中添加自定义标头:公共操作结果索引(){if(!HttpContext.User.Identity.IsAuthenticated){HttpContext.Response.AddHeader(“REQUIRES_AUTH”,“1”);}return View();}将JavaScript函数绑定到ajaxSuccess事件并检查标头是否存在:$(document).ajaxSuccess(函数(事件、请求、设置){if(request.getResponseHeader('REQUIRES_AUTH')==“1”){window.location='/';}});

让我再次引用@Steg描述的问题

我有一个和你类似的问题。我执行一个ajax请求可能的响应:将浏览器重定向到新页面将当前页面上的现有HTML表单替换为新的一

IMHO这是一个真正的挑战,必须正式扩展到当前的HTTP标准。

我相信新的Http标准将使用新的状态代码。意思:目前301/302告诉浏览器去把这个请求的内容取到一个新的位置。

在扩展标准中,它会说如果响应状态为:308(只是一个示例),那么浏览器应该将主页重定向到提供的位置。

话虽如此;我倾向于模仿这种未来的行为,因此当需要document.redirect时,我让服务器响应如下:

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

当JS获得“status:204”时,它检查x-status:308标头的存在,并将document.redirect指向位置标头中提供的页面。

这对你有意义吗?

如果您使用的是Spring Security,答案似乎对人们有用,但我发现扩展LoginUrlAuthenticationEntryPoint并添加特定代码来处理AJAX更为健壮。大多数示例拦截所有重定向,而不仅仅是身份验证失败。这对于我所从事的项目来说是不可取的。如果不希望缓存失败的AJAX请求,您可能会发现还需要扩展ExceptionTranslationFilter并重写“sendStartAuthentication”方法以删除缓存步骤。

示例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"));
    }
}

来源:1, 2

使用低级$.ajax()调用:

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

尝试此操作进行重定向:

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