如何处理 AJAX 请求中的会话超时问题

14

我相信大家都很熟悉使用 AJAX 的投票系统(嗯...就在右边 <----)。

我有一个类似的东西,当你投票赞成或反对时,它会使用 AJAX 从 votes.php 请求新值。问题是我正在使用会话获取用户 ID,以便每个人只能投一次票。如果他们在页面上坐了一个小时然后投票,那么会话就不存在了,该怎么处理这种情况呢?我应该将他们的页面重定向到登录界面吗?如果是这样,我该如何从被 AJAX 请求引用的 votes.php 页面执行此操作?是否有好的方法来处理这种情况?任何建议都将非常有帮助。

6个回答

11

考虑返回HTTP状态码401,并提供一个JSON对象来详细说明原因。如果你正在使用jQuery,那么它将跳转到error()回调函数,然后你可以解析你的对象。

$.ajax({
  data: {},
  dataType: 'html',
  success: function(data) {
    // do whatever here
  },
  type: 'POST',
  url: 'myserver.com',
  error: function(XMLHttpRequest, textStatus, errorThrown) {
    // XMLHttpRequest.responseText has your json string
    // XMLHttpRequest.status has the 401 status code
    if (XMLHttpRequest.status === 401) {
      location.href = 'login.php';
    }
  }
});

虽然我不再熟悉PHP,但这个方法适用于几乎任何环境。不过,您可能需要抑制自动登录表单重定向。在ASP.NET MVC中,框架将看到401并将默认的登录表单推回,并返回状态码200。


1
如果你能告诉我如何正确返回401,我将不会支付给你任何费用。 - Joe Phillips
在ASP.NET中,您只需设置Response.StatusCode = 401; 不过我不知道在PHP中该怎么做...或许有一天会有人建立一个网站来回答编程问题;-p - swilliams
我实际上尝试了一下,结果会弹出一个HTTP身份验证框,要求你输入用户名和密码。这不是我想要的功能。 - Joe Phillips
我猜可能是因为这一行代码,现在我正在测试它是否没有:header('WWW-Authenticate: Basic Realm="Login please"'); - Joe Phillips
你不一定非要使用401。500也可以,虽然它的表达不是那么明确清晰。 - swilliams

1

这是一个旧的帖子,但我想分享一下我的解决方案,它非常有效。

在我的框架中,系统会在用户尝试访问页面并且会话已超时或无效时将其重定向到登录表单。 我在登录表单顶部添加了以下HTML注释:

<!--LOGINFORM-->

我为jQuery的$.ajax函数创建了一个包装器,它在每个请求中检查这个字符串,如果存在,则显示一个对话框弹出窗口,提示他们的会话已超时。
您只需调用以下代码即可使用此功能:
ajax.get('http://someurl.com', function(data){
    //Do stuff
});

希望能对某人有所帮助。

var ajax = {
    check_login : function(resp){
        if (resp.substring(0, 16) === "<!--LOGINFORM-->"){
            // Show a popup or redirect them to login page!
            return true;
        }
        return false;
    },
    get : function(url, success){       
        if (typeof data =='undefined'){
            data = null;
        }

        $.ajax({
            url: url,
            type : 'GET',
            success : function(resp){
                if (!ajax.check_login(resp)) {
                    success(resp);
                }
            },
        });
    }   
};

1

你应该只在会话中存储用户身份的链接。使用会话来标识一个用户为x,然后从数据库获取用户x的信息。

如果你的问题是用户会话超时,那么你应该重新考虑如何使用你的会话。也许让它们持续到浏览器关闭?如果你真的想让它们有一个持续时间,那么也许可以定期向服务器发送请求以保持会话活动状态。

在你的php脚本中决定用户是否能够投票。如果会话未设置或者他们已经投过票,则返回一个客户端可以识别的消息。如果他们已经投过票,也许可以在JSON对象中返回"voted":"true"。使用JS解析此对象并理解其含义,采取适当的行动。如果会话未设置,也许可以返回"session_set":"false",然后使用window.location = "login.php"等进行javascript重定向。

只有在成功计数投票返回时才为用户增加计数器。


FYI,我只在会话中存储用户ID。 - Joe Phillips

0
你可以创建一个 JavaScript 函数,通过类似的方式每隔 10 分钟 ping 一次服务器。
setTimeout("Ping()", 60000); 

如果您想在用户连接到错误的会话时将其导航到登录页面,则应首先验证会话,如果失败,则发送一个。
header("Location: ...");

http://ca2.php.net/manual/en/function.header.php


0

你需要构建Javascript代码,使其能够接受特殊结果(例如-1代替通常的>=0数字,比如投票数),表示“抱歉,您已超时”,并重定向到重新登录页面(该页面可以作为可选参数包含一条消息,向用户解释超时原因等)。


0
从用户角度来看,最好的解决方案是弹出一条消息和登录表单,提示“您未登录或会话已超时”。Digg做得非常好。
至于实际的AJAX实现,swilliams的401建议很不错。另外,您也可以在失败时简单地返回一个特定的字符串。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接