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 如何在scanpy上做差异基因和通路富集?
  • ¥20 关于#硬件工程#的问题,请各位专家解答!
  • ¥15 关于#matlab#的问题:期望的系统闭环传递函数为G(s)=wn^2/s^2+2¢wn+wn^2阻尼系数¢=0.707,使系统具有较小的超调量
  • ¥15 FLUENT如何实现在堆积颗粒的上表面加载高斯热源
  • ¥30 截图中的mathematics程序转换成matlab
  • ¥15 动力学代码报错,维度不匹配
  • ¥15 Power query添加列问题
  • ¥50 Kubernetes&Fission&Eleasticsearch
  • ¥15 報錯:Person is not mapped,如何解決?
  • ¥15 c++头文件不能识别CDialog