会话超时时的PHP / MySQL更新数据库

时间:2014-07-12 14:25:30

标签: php mysql session cookies timeout

我正在开发一个“Flash网站”。在这个程序中,我想添加一个依赖于会话的“在线用户”列表:当用户登录时会启动会话,并且用户在数据库中被标记为“在线”。当注销关闭浏览器时,用户在数据库中被标记为“脱机”。

我知道在浏览器关闭时运行某些功能需要使用Javascript,并且它也不安全:如果浏览器崩溃,则函数将无法运行。这就是为什么如果用户注销或用户的会话超时,我已决定更新数据库。

我一直在寻找会话超时,并遇到了许多其他标记为重复的内容:How do I expire a PHP session after 30 minutes?

答案方法的问题是;这是一个条件句,检查用户的最后一次活动是否是X秒前,如果没有活动,则超时。在某些网站中很有用,但对于在线用户列表没用,因为它在发送新请求时更新,并且因为用户关闭浏览器后不会有任何请求。

在其他答案中也提到使用session.gc_maxlifetimesession.cookie_lifetime,但最佳答案指出使用它们是一个坏主意;一个不破坏会话,只破坏cookie,另一个是“成本密集型”。

我想要的是用户超时和数据库更新并将用户标记为离线不使用使用If-Conditional句子,或者可能只使用不同的If条件句子必须在用户登录时使用一次,如计时器或其他东西,每当发送请求时,计时器重新开始......这些只是我到目前为止关于如何解决这个问题的想法。

但是,我该怎么做?如果答案非常简单明了,我很抱歉,我对PHP很新。

编辑:长话短说:

我想在用户关闭浏览器后运行一个功能,或者在20分钟内处于非活动状态。

澄清...

我想在不活动20分钟后更新数据库,即使浏览器已关闭。

5 个答案:

答案 0 :(得分:1)

if (!isset($_SESSION['CREATED'])) {
    $_SESSION['CREATED'] = time();
} else if (time() - $_SESSION['CREATED'] > 1800) {
    // session started more than 30 minutes ago
    session_regenerate_id(true);    // change session ID for the current session an invalidate old session ID
    $_SESSION['CREATED'] = time();  // update creation time
}

还读这个 http://php.net/manual/en/session.configuration.php#ini.session.gc-maxlifetime

答案 1 :(得分:1)

您希望使用以下信息来捕获事件: How to capture the browser window close event?

然后,您需要在服务器上使用sessionID调用该事件处理程序中的页面。

该页面调用您设置的本地脚本,页面或服务,以延迟20分钟并使会话到期。如果您想在用户在到期前重新访问时重新启动时钟,则需要包含一种中断或取消该脚本进程的方法,并且您需要将SessionID保留在需要查找的cookie中每页加载。如果找到并匹配cookie的SessionID,则超时被中断/停止(如果它还在继续)。如果已经完成,则需要发布新的SessionID。

如果您同时有很多这些取消,您将在服务器上排队,并让流程定期检查队列并根据需要使它们到期。

大多数网站避免这一切的方式是设置30分钟或任何会话超时,无论访问者是否活跃,都会强制执行。

答案 2 :(得分:1)

  

我希望在浏览器运行20分钟后更新数据库   闭合。

我认为这不可能与浏览器被关闭(可靠)有关。如果他们单击注销按钮,您显然可以运行一些代码以将用户标记为已注销。您可以使用您提到的功能指定会话有多长时间,但这样做会使cookie在客户端被删除,它不会在服务器端触发任何内容。

关于你唯一可以做的就是跟踪用户上次活动的时间,以及他们是否在一段时间内没有活动,假设他们已经离开了。因此,只需在用户表中添加一个字段,并存储其上一个活动的日期时间或unix时间戳。然后,您可以每隔几分钟运行一次cron作业,将用户标记为已注销,或者您只需修改SQL查询即可仅提取最后一次活动少于20分钟的用户。

答案 3 :(得分:1)

您可以借助具有最后活动字段的在线用户表

来完成此操作
window.setInterval(function() {
    $.ajax({      
      url: "http://yourdomain/updateLastactive/?uid=" + User_ID,
      success: function(data) {

      }
    }); 
}, 5000); // 5 seconds 

此页面将更新当前时间戳作为该用户的最后一个活动

然后在线用户查询,您可以执行以下操作,

SELECT UID FROM ONLINE_USERS WHERE LAST_ACTIVE >  DATE_SUB(NOW(), INTERVAL 30 MINUTE));

答案 4 :(得分:0)

执行此操作的最简单方法是编写一个查看会话时间戳的MySQL存储过程,并在会话数据为>时删除会话数据。 20分钟。您也可以将其作为外部cron作业,但存储过程会更好。

此外,每次用户连接时都需要刷新会话时间戳。

如果您想确保在用户仍然打开“页面”时不删除会话,那么一些后台JavaScript刷新到您的站点将充当保持活动状态。请注意,如果用户关闭“窗口”或“标签”,它将与整个浏览器关闭相同 - 我不确定您是否可以对此做任何事情。

当然,要执行此操作,您需要将会话存储在MySQL中。

TL; DR

  • 如果session_timestamp>,则MySQL存储过程或cron作业删除会话20分钟
  • 客户端Javascript执行ajax刷新以保持会话打开
  • 每次请求“页面”时,会话时间戳都会更新(浏览器或ajax)。