我的自动重定向登录页面的方法在PHP中正确吗?

我的自动重定向登录页面的方法在PHP中正确吗?,php,session,logout,Php,Session,Logout,我有一个社区网站,一个用户可以有很多朋友。当显示他的所有朋友时,我想包括他的朋友是在线还是离线 我的方法是,当用户登录时,在状态列“online”上创建一个会话并更新users表。如果他单击注销按钮,那么我将把状态设置为“脱机”。如果他没有点击注销按钮就关闭浏览器怎么办?以下是我想做的: session_start(); if (!isset($_SESSION['LAST_ACTIVITY'])) { // initiate value $_SESSION['LAST_ACTI

我有一个社区网站,一个用户可以有很多朋友。当显示他的所有朋友时,我想包括他的朋友是在线还是离线

我的方法是,当用户登录时,在状态列“online”上创建一个会话并更新users表。如果他单击注销按钮,那么我将把状态设置为“脱机”。如果他没有点击注销按钮就关闭浏览器怎么办?以下是我想做的:

session_start();
if (!isset($_SESSION['LAST_ACTIVITY'])) {
    // initiate value
    $_SESSION['LAST_ACTIVITY'] = time();
}
if (time() - $_SESSION['LAST_ACTIVITY'] > 3600) {
    // last activity is more than 10 minutes ago
    session_destroy();
    //direct to a php, say this user is idle and thus status = offline
    header("location: update_status.php?user=".$_SESSION['username']."&status=offline");
    // den redirect them to login page
} else {
    // update last activity timestamp
    $_SESSION['LAST_ACTIVITY'] = time();
}
这是一种合适的方式吗


编辑: 查看一些简单的示例代码,了解如何在用户联机时进行检查以及在用户访问页面时进行更新,这会很有帮助


我是否需要在每个链接中都包含
php?user=$\u SESSION['userid']

我认为这是行不通的。当用户关闭浏览器时,您在此处输入的代码将永远不会被调用

一种可能的方法是,每当用户调用页面时,保存用户上次在数据库中处于活动状态的时间。如果用户上次活动的时间超过5分钟,您可以将其视为脱机,并将其显示给其他用户

我认为phpbb3就是这样做的


当用户关闭浏览器时获取一个事件是很麻烦的,而且并不总是有效。

我发现您的代码中有几个问题:

if (time() - $_SESSION['LAST_ACTIVITY'] > 3600) {
  // last activity is more than 10 minutes ago
  session_destroy();
  //direct to a php, say this user is idle and thus status = offline
  header("location: update_status.php?user=".$_SESSION['username']."&status=offline");
}
在这段代码中,您销毁会话,然后从刚才销毁的会话中获取用户名

顺便说一句,如果我理解你的问题,你就不会得到这个代码的预期行为


您检查用户是否正在访问您的站点(您启动的会话的所有者)已空闲超过10分钟,如果为真,则在该用户尝试重新进入站点时立即断开他的连接

据我所知,您的解决方案是,即使用户最后一次访问该网站已经超过10分钟了,该用户仍被标记为在线


您应该在数据库中保存上次用户在您的站点上活动的时间。当用户查看好友列表时,您这次也会查看好友列表,并查看是否超过10分钟前,即好友处于非活动状态。

最好的方法是为登录的用户存储活动时间。当他们导航到某个页面或执行某个操作时,用当前时间更新他们在数据库中的“上次活动”时间。如果此时间超出阈值(例如,15分钟),则可以将该用户分类为不再活动。

在标题位置重定向后,明确地写下以下行:

die();

并非所有的用户代理(浏览器、web爬行器等)都会侦听您的重定向头。删除脚本是确保他们不会获取页面其余部分的唯一安全方法。

如果您仅通过在线/离线专栏确定用户是否已注销,那么用户关闭浏览器窗口(不点击注销链接/按钮)仍将登录

这里的正常方法是跟踪用户何时在站点上移动,存储他们最后一次导航到页面的时间。然后,设置一个预定义的常量,确定是什么让用户处于活动状态(比如说在过去15分钟内浏览页面),然后在SQL查询中使用该常量来抓取访问用户的朋友以及在过去15分钟内访问过站点的每个用户

在将时间存储为datetime的SQL查询中(这是MySQL的查询),这可能类似于:

SELECT col1, col2, col3 FROM Users WHERE DATE_ADD(LastActive, INTERVAL 15 MINUTE) > NOW() AND UserIsFriendOfCurrentUser

当然,您的查询需要进行调整,以更好地适应您的设置,但希望您能理解。

在我们的项目中,我们使用以下技术:

  • 登录后的每个用户都与会话id关联
  • 浏览器通过计时器通过AJAX发送“活动请求”
  • 轻量级服务器端脚本更新数据库中的最后一个活动,即搜索 按会话id列出的用户
  • cronjob更新所有超时用户,将其标记为脱机 (实际上会话id为空),并且 为每个用户执行注销例程 使用户可以避免服务器上损坏的数据 业务层
  • 用户怎么办? 直到用户关闭浏览器-活动正在更新。关闭浏览器后,用户超时并标记为脱机。当用户试图到达任何需要授权的位置时—我们尝试做的第一件事是通过会话id在DB中找到他,如果不是—他只能看到登录表单(即include();exit();)


    糟糕的是,选项卡式浏览器在同一窗口中为每个打开的选项卡使用相同的会话id。但我们的项目是一个游戏,不允许来自一个浏览器的多用户。实际上,当两个或多个用户尝试从一个浏览器的不同选项卡登录时,这种情况非常罕见。

    您不应该使用
    $\u SESSION
    存储上次活动时间。每次用户转到某个页面时,使用用户表中的当前时间更新名为
    last\u activity
    的列:

    <?php
    session_start();
    
    $userId = (int)$_SESSION['user']; // make sure it's an integer
    $db->exec('
        UPDATE users 
        SET last_activity = NOW() 
        WHERE id = ' . $_SESSION['id']
    );
    //...
    

    数据库会话可能是管理谁在线和谁不在线的好方法。理论上,它们应该自行失效。我在我的博客上写了一篇关于它的指南,你可以在


    这还增加了一个额外的好处,允许您在需要时远程终止用户会话:)

    这就是我要做的。但是如果用户再也没有回来呢?然后他再也不会加载另一个页面将自己设置为脱机。您应该将该脚本放在某个地方,每隔10分钟左右调用一次,可能由cronjob调用—您不需要cronjob。当其他人想知道他是否是唯一的时,只需检查他的活动。+1:为了一个好时机,偶尔禁用浏览器重定向,并注意它完全绕过了许多使用重定向安全的劣质身份验证系统。
    SELECT 
        u.user_name, u.name, etc,
        IF(
            UNIX_TIMESTAMP() - UNIX_TIMESTAMP(u.last_activity) < 300, 
            1, 0
        ) as online
        ... 
    
    $friends = $db->query(/* above SQL */);
    foreach($friends as $friend)
    {
        if($friend['online'] == 1)
            // online specific stuff
        else
            // offline specific stuff
    }