dongmi1663 2019-03-29 12:50
浏览 144
已采纳

会话ID重新生效登录 - 在后续运行中将我从当前会话中踢出

I have this login mechanism with an additional authentication barrier presented before the user can change sensitive information (such as their password, email, etc.) through their profile.

There is a pre-session on the login page that I use for verifying the CSRF token, and I have code responsible for regenerating the session ID before the current session is given the user data and authentication status.

For the login process, everything goes fine. The session ID before and after logging in are different. No problems here. The problem begins when I go to authentication.php, which serves as a barrier presented to the user before they can change their password. Upon successfully validating the provided password against the hash from the database, I would set a new session variable named "authenticated" that gives access to the next page, pass-change.php. Before "authenticated" is set, the session ID must be, again, regenerated.

That's where my problem lies.

Instead of taking me to pass-change.php with a brand new session ID, it destroys the session; consequently, I am taken back to login.php, presumably because $_SESSION['loggedin'] is no longer set.

// This is my session_start() function

    function my_session_start() {
      session_start();
      if (isset($_SESSION['destroyed'])) {
         // checks if session has been 'destroyed' for more than 5 minutes
         if ($_SESSION['destroyed'] < time() - 300) {
           // if true, wipe all session variables and throw exception
           $_SESSION = array();
           throw new Exception('This session is obsolete');
         }
         if (isset($_SESSION['new_session_id'])) {
           // if new_session_id is still set, close the session and attempt to start a new session with it
           session_commit();
           session_id($_SESSION['new_session_id']);
           session_start();
           return;
         }
      }
    }
    my_session_start();

// This is my session_regenerate_id() function

    function my_session_regenerate_id() {
      // new session ID is created and stored for later use
      $new_session_id = session_create_id();
      $_SESSION['new_session_id'] = $new_session_id;
      // set the current session as 'destroyed' and save current time
      $_SESSION['destroyed'] = time();
      // close session
      session_commit();
      // set the new ID we created previously and start a new session
      session_id($new_session_id);
      ini_set('session.use_strict_mode', '0');
      session_start();
      ini_set('session.use_strict_mode', '1');
      // unset these variables as they should not be with the new session
      unset($_SESSION['destroyed']);
      unset($_SESSION['new_session_id']);
    }

// Sessions are always started at the beginning of every file. my_session_regenerate_id() is called right before I define session variables containing authentication flags or user data. This is done at login.php after password is checked against the hash and deemed correct; and also called at authentication.php after the user provides their correct password.

// this is the part where I call my_session_regenerate_id() at authentication.php

if (password_verify($pass, $hash)) {
    my_session_regenerate_id();
    $_SESSION["authenticated"] = time();
    header('Location: pass-change.php');
}

// some pages redirect when you're not logged in

if (!isset($_SESSION["loggedin"])) {
    header('Location: login.php');

I expect the session to retain its status after my_session_regenerate_id() is called at authentication.php, but it gets destroyed. All it should be doing is: set current session as 'destroyed', create new session ID and change to it, while retaining all other user data and authentication flags such as $_SESSION['loggedin'].

EDIT

As requested, here are the results from printing all session variable data:

Before login, at login.php:

array(2) {
  ["usertoken"]=>
  string(64) "519f82f974fb8e79b30ee950be9ba63048278105bd8e983fa832e754aaf47b3c"
  ["usrtokentime"]=>
  int(1553865620)
}

After first run of session ID regeneration, at profile.php:

Session ID changed after login

array(7) {
  ["lastLogin"]=>
  int(1553864997)
  ["loggedin"]=>
  string(0) ""
  ["registerDate"]=>
  int(1553605077)
  ["name"]=>
  string(14) "User Name"
  ["email"]=>
  string(26) "user.email@gmail.com"
  ["type"]=>
  string(1) "A"
  ["usertoken"]=>
  string(0) ""
}

Second run of session ID regeneration. After submitting the form at authentication.php and being thrown back to login.php:

Session ID changed again

array(3) {
  ["authenticated"]=>
  int(1553865804)
  ["usertoken"]=>
  string(64) "ba454364870f5d8cdfd4e5a3213d3a34117f161c098c97060e70327d3a983501"
  ["usrtokentime"]=>
  int(1553865804)
}

So, only "authenticated" session variable survived. All others were wiped out.

  • 写回答

1条回答 默认 最新

  • dtvq4978 2019-03-29 14:12
    关注

    Thanks to 04FS, I was able to pinpoint the problem.

    The my_session_regenerate_id() function is wiping all the session variables when it is called. The solution is to set all the variables after the function call, and that was easy to do in my code, because a prepared statement object was already available at that point to pull in all the data.

    This is how my function call code looks like now at authentication.php:

    if (password_verify($pass, $hash)) {
        my_session_regenerate_id();
        $_SESSION["authenticated"] = time();
        $_SESSION["lastLogin"] = $res['lastLogin'];
        $_SESSION["loggedin"] = "";
        $_SESSION["registerDate"] = $res['registerDate'];
        $_SESSION["name"] = $res['name'];
        $_SESSION["email"] = $res['email'];
        $_SESSION["type"] = $res['type'];
        $_SESSION["usertoken"] = "";
        header('Location: pass-change.php');
    }
    
    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

悬赏问题

  • ¥15 Vue3 大型图片数据拖动排序
  • ¥15 划分vlan后不通了
  • ¥15 GDI处理通道视频时总是带有白色锯齿
  • ¥20 用雷电模拟器安装百达屋apk一直闪退
  • ¥15 算能科技20240506咨询(拒绝大模型回答)
  • ¥15 自适应 AR 模型 参数估计Matlab程序
  • ¥100 角动量包络面如何用MATLAB绘制
  • ¥15 merge函数占用内存过大
  • ¥15 使用EMD去噪处理RML2016数据集时候的原理
  • ¥15 神经网络预测均方误差很小 但是图像上看着差别太大