jQuery Ajax调用后如何管理重定向请求

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

如何使用jQuery 1.2.6从Ajax调用管理重定向指令?


#1楼

您还可以挂钩XMLHttpRequest发送原型。 这将适用于具有一个处理程序的所有发送(jQuery / dojo / etc)。

我编写了这段代码来处理500页的过期错误,但是它应该也可以捕获200个重定向。 准备好XMLHttpRequest上的Wikipedia条目onreadystatechange,以了解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);
}

#2楼

我只想分享我的方法,因为这可能会帮助某人:

我基本上包括一个JavaScript模块,该模块处理身份验证之类的内容,例如显示用户名,在这种情况下,还处理重定向到登录页面的情况

我的情况:我们基本上有一个ISA服务器,在这两个服务器之间侦听所有请求, 并以302和登录页面的位置标头作为响应

在我的JavaScript模块中,我最初的方法

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

问题(这里已经提到了很多问题)是浏览器自己处理重定向,因此我的ajaxComplete回调从未被调用过,而是得到了已经重定向的Login页面响应 ,显然是status 200 。 问题:您如何检测成功的200响应是您的实际登录页面还是其他任意页面?

解决方案

由于无法捕获302重定向响应,因此在登录页面上添加了LoginPage标头,其中包含登录页面本身的URL。 现在,在模块中,我侦听标头并进行重定向:

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

...就像魅​​力:)。 您可能想知道为什么我将URL包含在LoginPage标头中...基本上是因为我找不到确定从xhr对象进行自动位置重定向而导致的GET ...


#3楼

弗拉基米尔·普鲁德尼科夫和托马斯·汉森说的话:

  • 更改服务器端代码以检测它是否为XHR。 如果是,请将重定向的响应代码设置为278。在django中:
  if request.is_ajax(): response.status_code = 278 

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

  • 在您的JS中,确保通过Ajax提交表单,检查响应代码并根据需要重定向:
 $('#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); }); 

#4楼

我认为处理此问题的更好方法是利用现有的HTTP协议响应代码,尤其是401 Unauthorized

这是我解决的方法:

  1. 服务器端:如果会话过期,并且请求是ajax。 发送401响应码标头
  2. 客户端:绑定到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'; } }); 

IMO这是更通用的,您没有编写新的自定义规范/标题。 您也不必修改任何现有的ajax调用。

编辑:根据下面的@Rob的注释,401(身份验证错误的HTTP状态代码)应作为指示符。 有关更多详细信息,请参见403禁止与401未经授权的HTTP响应 。 话虽如此,某些Web框架同时使用403进行身份验证和授权错误-因此请进行相应调整。 谢谢罗伯。


#5楼

如果您还想传递值,那么还可以设置会话变量并访问Eg:在您的jsp中,您可以编写

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

然后,您可以将此临时值存储在javascript变量中,然后进行操作


#6楼

头文件解决方案没有任何成功-我的ajaxSuccess / ajaxComplete方法中从未将它们拾取。 我在自定义响应中使用了Steg的答案,但在JS方面做了一些修改。 我设置了在每个函数中调用的方法,因此可以使用标准的$.get$.post方法。

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);
    }
}

使用中的示例...

function submitAjaxForm(form, url, action) {
    //Lock form
    form.find('.ajax-submit').hide();
    form.find('.loader').show();

    $.post(url, form.serialize(), function (d) {
        //Unlock for
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值