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

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


当前回答

我通过在login.php页面中放置以下内容来解决这个问题。

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

其他回答

这对我有用:

success: function(data, textStatus, xhr) {

        console.log(xhr.status);
}

一旦成功,ajax将获得浏览器从服务器获得的相同状态代码并执行它。

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

我知道这个话题已经过时了,但我将给出另一种我已经发现并在这里描述过的方法。基本上,我使用的是ASP.MVC和WIF(但这对于本主题的上下文来说并不重要——无论使用哪种框架,答案都是足够的。线索保持不变——在执行ajax请求时处理与身份验证失败相关的问题)。

下面显示的方法可以应用于所有开箱即用的ajax请求(如果它们显然没有重新定义beforeEnd事件)。

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

在执行任何ajax请求之前,调用CheckPulse方法(可以是任何最简单的控制器方法):

[Authorize]
public virtual void CheckPulse() {}

如果用户未经身份验证(令牌已过期),则无法访问该方法(受Authorize属性保护)。因为框架在令牌过期时处理身份验证,所以它将http状态302置于响应中。如果您不希望浏览器透明地处理302响应,请在Global.asax中捕获它,并将响应状态更改为200 OK。此外,添加header,它指示您以特殊方式处理此类响应(稍后在客户端):

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

最后在客户端检查这样的自定义头。如果存在,则应该完成到登录页面的完全重定向(在我的情况下,window.location被来自请求的url替换,该url由我的框架自动处理)。

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

我认为更好的处理方法是利用现有的HTTP协议响应代码,特别是401未授权。

我是这样解决的:

服务器端:如果会话过期,请求为ajax。发送401响应代码头客户端:绑定到ajax事件$('body').bind('ajaxSuccess',函数(事件,请求,设置){if(401==请求状态){window.location='/users/login';}}).bind('ajaxError',函数(事件、请求、设置){if(401==请求状态){window.location='/users/login';}});

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

编辑:根据@Rob下面的评论,401(验证错误的HTTP状态代码)应该是指示符。有关详细信息,请参阅403禁止与401未授权HTTP响应。尽管如此,一些web框架使用403来处理身份验证和授权错误,因此进行相应的调整。谢谢Rob。

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

向响应中添加自定义标头:公共操作结果索引(){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='/';}});