浏览器强制关闭或会话过期后,在数据库上更改登录状态

时间:2017-12-06 09:49:53

标签: php mysql codeigniter session

我在MySQL中有一个用户登录数据,条件是用户只能在会话中登录1次。如果使用注销按钮,代码运行良好,但如果用户关闭浏览器

// user_table in MySQL
   user_id      user_username      user_password      is_login
     1              xyzabc             xxxxx             0  // 0 is not
     2              abcdef             xxxxx             1  // 1 is login
     3              efghij             xxxxx             1

我使用is_login阻止来自第二登录用户的访问。因此,每个帐户只能登录一次is_login我们曾经将用户从集合is_login的登录会话中踢到0

// Inside my login function
public function login()
{
   ... some validation login code ...
   // User ID accepted & login = TRUE
   $this->session->set_userdata('id', $data->user_id);
   // this query is in model, I just copy it to here
   $this->db->query('UPDATE user_table SET is_login = "1" WHERE user_id = ".$id."');
   $this->session->sess_expiration = 7200;
   $this->session->sess_expire_on_close = TRUE;
}

// Logout function in controller
public function logout() {
   $id = $this->session->userdata('id');
   // this query is in model, I just copy it to here
   $this->db->query('UPDATE user_table SET is_login = "0" WHERE user_id = ".$id."');
   $this->session->sess_destroy();
}

如果用户使用logout功能注销,则代码运行良好。

is_login列将再次设置在0上。但是,如果浏览器强制关闭is_login状态仍为1。任何解决方案?

1 个答案:

答案 0 :(得分:1)

  1. 如@Tpojka所示,将is_login列更改为INT(11)
  2. 在用户表中添加另一列以显示上次用户活动
  3. 如果当前系统时间和上次用户活动大于到期时间,则向SET is_login = 0添加cronjob
  4. 每当用户登录时,将时间()值从php存储到DB
  5. 将相同的登录时间()值存储到用户会话中。因此,每次用户刷新页面时,您都会检查与DB会话中的值,以了解用户是否相同。如果没有,请注销用户并销毁相同内容。这可能意味着用户已从其他设备登录,因此他/她应该从当前浏览器注销
  6. 每次用户发送请求并且is_login值与您在DB中的值匹配时,您可以在用户会话中添加和更新其他值。例如dte_last_activity,那么你可以理解,如果会话已经过期或者没有为用户过期。不要依赖服务器的会话到期时间,因为您可能需要不同的到期时间。
  7. 好吧,假设我们有一个如下所示的用户表:

     CREATE TABLE IF NOT EXISTS `system_users` (
       `id` smallint(5) unsigned NOT NULL,
       `fullname` varchar(90) COLLATE utf8_persian_ci NOT NULL,
       `username` varchar(40) COLLATE utf8_persian_ci NOT NULL,
       `password` varchar(32) COLLATE utf8_persian_ci DEFAULT NULL,
       `dte_login` int(11) unsigned NOT NULL DEFAULT '0',
       `dte_activity` int(11) unsigned NOT NULL DEFAULT '0',
     ) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_persian_ci;
    

    dte_login 是我们在用户登录时设置到数据库中的时间戳值 dte_activity 是上次用户从您的服务器请求内容时的时间戳值,当然他是登录的

    请注意,只有在您需要检查用户是否仍然有效时才需要 dte_activity

    function login($username, $password) {
        $result = false;
    
        // Check from DB that the username and password is valid or not
        // IF user is valid, retrieve user_id from DB
        If (USER_IS_VALID) {
            $_SESSION['user_id'] = $user_id;
            $_SESSION['dte_activity'] = time();
            $_SESSION['dte_login'] = time();
    
            $result = true;
        }
    
        return $result;
    }
    

    现在,只要用户要求访问某个页面,您就可以调用以下示例函数:

    function checkLogin() {
        $result = false;
    
        if (!empty($_SESSION['user_id'])) {
             // This means that somebody is already logged in
             $user_id = $_SESSION['user_id'];
             $dte_login = $_SESION['dte_login'];
    
             // We need to check if the user which is login is the same as the last user that used our website so we compare the dte_login value that we stored in session with what we have in DB
             $db_connection->query("SELECT `id` FROM `system_users` WHERE `id`={$user_id} AND `dte_login`={$dte_login};");             
             // If the above query return no result, it means that someone else logged in meanwhile and we have to log out the current user 
    
             if ($db_connection->num_rows>0) {
                 // Now we need to check if his/her session is still valid or not
                 $EXPIERY = 300; // in seconds (in this case, 5 minutes) 
                 $now = time();
                 if ($now-$_SESSION['dte_activity']<$EXPIERY) {
                     // The user session is still valid and we need to update database
                     $db_connection->query("UPDATE `system_users` SET `dte_activity`={$now} WHERE id={$user_id};");
                     $_SESSION['dte_activity'] = $now;
    
                     $result = true; // Means that someone is active
                 } else {
                     session_destroy();
                 }
             } else {
                 session_destroy();
             }
        }
    
        return $result;
    }