为什么我的cookie在浏览器关闭时没有到期?

时间:2014-06-15 23:51:16

标签: php security session session-cookies

我写了一个可以帮助我完成应用程序身份验证过程的类。

想法是

  1. 将会话存储引擎从服务器上的文件更改为 数据库中。
  2. 创建一个随机会话ID,而不是在PHP上转发 为我生成会话ID
  3. 更改会话的长度 id为允许的最大值(即40个字符)
  4. 将新会话ID与user_id(应用程序用户标识符)以及用户的IP地址和用户代理信息一起存储到表中。
  5. 设置空闲时间,以便系统自动销毁用户 空闲时间1800秒后的会话。
  6. 执行上述操作后,在每个请求的页面上,我都会检查以下内容是否为真

    1. 用户浏览器中的有效会话ID。
    2. 确保我可以将当​​前的IP地址和当前的用户代理信息与登录时捕获的信息相匹配。
    3. 如果会话有效且未过期,则使用它,否则如果user_is可用(即登录尝试),则创建一个新会话。
    4. 我看到的问题是,当用户关闭他/她的浏览器时,包含会话ID的cookie仍然可用。为什么cookie在浏览器关闭时不会到期?

      另外,您是否在我的代码中看到任何缺陷/流程或我可以采取哪些措施来提高身份验证过程的安全性?

      感谢您的帮助和时间

      以下是我的班级

      <?php
      
      ini_set('session.hash_function', 1);
      ini_set('session.hash_bits_per_character', 4);
      
      class sessionManager {
          private $db;
          private $user_id;
          private $user_ip;
          private $user_agent;
          private $autherizedUser = false;
          private $cookie_name;
          private $current_session_id;
          private $max_session_idle_time = 1800;
          private $current_time;
      
      
          public function __construct($name, $user_id = NULL, $limit = 0, $path = '/', $domain = null, $secure = null){
              // Set the cookie name
              session_name($name);
              // pass the current user_id. This is only useful at the time of login "to start a new session"
              $this->user_id = $user_id;
      
              //assign the cookie name that will be used for the session
              $this->cookie_name = $name;
      
              $this->current_time = time();
              if(isset($_SERVER['REMOTE_ADDR']))
                  $this->user_ip = $_SERVER['REMOTE_ADDR'];
      
              if(isset($_SERVER['HTTP_USER_AGENT']))
                  $this->user_agent = $_SERVER['HTTP_USER_AGENT'];
      
              // Set SSL level
              $https = isset($secure) ? $secure : isset($_SERVER['HTTPS']);
      
              //set the session storage to point custom method
              session_set_save_handler(
                  array($this, "open"),
                  array($this, "close"),
                  array($this, "read"),
                  array($this, "write"),
                  array($this, "delete"),
                  array($this, "garbageCollector")
              );
      
              //Set session cookie options
              session_set_cookie_params($limit, $path, $domain, $https, true);
      
              //set the current session_id that is stored in the cookie
              if(!empty($this->cookie_name) && isset($_COOKIE[$this->cookie_name]) && !empty($_COOKIE[$this->cookie_name]))
                  $this->current_session_id = $_COOKIE[$this->cookie_name];
      
      
              //if there is no IP detected - make it invalid
              if( empty($this->user_ip) || empty($this->user_agent)  ){
                  echo 'Invalid Request!!!';
                  exit();
              }
              //start session
              if(session_id() == '')
                  session_start();
      
              // Make sure the session hasn't expired, and destroy it if it has   
              if(  $this->isValidSession()   ){
      
                  if($this->isHijacking()){
                      //destroy the session
                      $this->destroy();
      
                  } else {
                      //re-set the idle timeout
                      $_SESSION['MA_IDLE_TIMEOUT'] = $this->current_time + $this->max_session_idle_time;
                      $this->autherizedUser = true;
                  }
      
              } else {
                  //make sure there is a user_id passed before creating a new session
                  if( !empty($this->user_id) ){
                      //destroy the session
                      $this->destroy();
                      //start a new session
                      $new_session_id = $this->generateSessionID();
                      session_id($new_session_id);
                      session_start();
                      $this->setSessionValues();
                      $this->autherizedUser = true;
                  }
              }
          }
      
          public function destroy(){
              $this->autherizedUser = false;
              session_unset();
              session_destroy();
              unset($_COOKIE[SESSION_NAME]);
          }
      
          /**
           * This function regenerates a new ID and invalidates the old session. This should be called whenever permission
           * levels for a user change.
           */
          private function setSessionValues(){
      
              $_SESSION = array();
      
              //set the IP address info
              $_SESSION['MA_IP_ADDRESS'] = $this->user_ip;
      
              // save the agent information
              $_SESSION['MA_USER_AGENT'] = $this->user_agent;
      
              //set the idle timeout
              $_SESSION['MA_IDLE_TIMEOUT'] = $this->current_time + $this->max_session_idle_time;
          }
      
          //This function is used to see if a session has expired or not.
          private function isValidSession(){
              if(empty($this->current_session_id) ) 
                  return false;
      
              if( !isset($_SESSION['MA_IP_ADDRESS']) || !isset($_SESSION['MA_USER_AGENT']) || !isset($_SESSION['MA_IDLE_TIMEOUT']) )
                  return false;
      
              if( empty($_SESSION['MA_IP_ADDRESS']) || empty($_SESSION['MA_USER_AGENT']) || empty($_SESSION['MA_IDLE_TIMEOUT']) )
                  return false;
      
              //if the session expired - make it invalid
              if( $_SESSION['MA_IDLE_TIMEOUT'] < $this->current_time   )
                  return false;
      
              //the session is valid
              return true;
          }
      
      
              //This function is used to see if a session has expired or not.
          private function isHijacking(){
      
              //if the set IP address no not match the current user's IP address value - make it invalid
              if( $_SESSION['MA_IP_ADDRESS'] != $this->user_ip )
                  return true;
      
              //if the set user agent value do not match the current user agent value - make it invalid
              if(   $_SESSION['MA_USER_AGENT'] != $this->user_agent  )
                  return true;
      
              //the session is valid
              return false;
          }
      
          public function isAutherized(){
              return $this->autherizedUser;
          }
      
      
          private function generateSessionID($len = 40) {
              $characters = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ,-';
              $newStr = '';
              $maxLen = strlen($characters)-1;
              for ($i = 0; $i < $len; ++$i) 
                  $newStr .= $characters[rand(0, $maxLen)];
      
              return $newStr;
          }
      
          //open the database connection for the session storage engine
          public function open(){
              $this->db = new connection();
              if($this->db)
                  return true;
      
              // Return False
              return false;
          }
      
          //close the database connection for the session storage engine
          public function close(){
      
              if($this->db->endConnection())
                  return true;
      
              // Return False
              return false;
          }
      
          //read current session variables from the session database
          public function read($id){
              // Set query
              $data = $this->db->getDataSet('SELECT data FROM sessions WHERE session_id = ?', array($id));
      
              if(count($data) == 1)
                      return $data[0]['data'];
      
      
              return '';
          }
      
          //replace the existing data using the current session id
          public function write($id, $data){
      
              // Set query  
              $replace = $this->db->processQuery('INSERT INTO sessions(session_id, access, data, user_id) VALUES (?, ?, ?, ?)
                                                  ON DUPLICATE KEY UPDATE
                                                  session_id = ?,
                                                  access = ?,
                                                  data = ?', array($id, $this->current_time, $data, $this->user_id, $id, $this->current_time, $data));
      
              if($replace)
                  return true;
      
              // Return False
              return false;
          }
      
          //delete a session record from the storage engine
          public function delete($id){
              // Set query
              $delete = $this->db->processQuery('DELETE FROM sessions WHERE session_id = ? OR user_id IS NULL', array($id));
      
              if($delete)
                  return true;
      
              // Return False
              return false;
          } 
      
          //deletes all expired session - if the access time is less that current time
          public function garbageCollector($max){
              // Calculate what is to be deemed old
              $old = $this->current_time - $max;
              // Set query
              $delete = $this->db->processQuery('DELETE FROM sessions WHERE access < ?', array($old));
      
              if($delete)
                  return true;
      
              // Return False
              return false;
          }   
      
      }
      
      ?>
      

      这里是我如何使用这个类 当用户登录时我检查用户名和密码。然后我这样做

                  $session = new sessionManager(SESSION_NAME, $user[0]['user_id'], SESSION_MAX_AVAILABLE, SESSION_SAVE_PATH, SESSION_SAVE_URL, SESSION_HTTPS_ONLY);                   
      
                  if( $session->isAutherized() === true ){
                      header('Location: '.ABSOLUTE_PATH.'index.php');
                      exit();
                  }
      

      然后每个页面执行以下代码,以确保用户是Autherized

      $session = new sessionManager(SESSION_NAME, NULL, SESSION_MAX_AVAILABLE, SESSION_SAVE_PATH, SESSION_SAVE_URL, SESSION_HTTPS_ONLY);
      
          $session_id = $_COOKIE[SESSION_NAME];
          $access_time = time();
      
      if( $session->isAutherized() === false || empty($session_id) ){
          $session->destroy();
          header('Location: '.ABSOLUTE_PATH.'login.php');
          exit();
      }
      

0 个答案:

没有答案