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

Php 为什么浏览器关闭时我的cookie没有过期?,php,security,session,session-cookies,Php,Security,Session,Session Cookies,我编写了一个类,它将帮助我完成应用程序身份验证过程 我们的想法是 将会话存储引擎从服务器上的文件更改为 数据库 创建一个随机会话id,不要在PHP上中继到 为我生成会话id 更改会话的长度 id设置为允许的最大值(即40个字符) 将新会话id与用户id(应用程序用户标识符,)以及用户的IP地址和用户代理信息一起存储到表中 设置空闲超时,以便系统自动销毁用户 1800秒空闲时间后的会话 在实现上述功能后,在每个请求的页面上,我检查以下内容是否正确 用户浏览器中的有效会话ID 确保我可以将当前IP地

我编写了一个类,它将帮助我完成应用程序身份验证过程

我们的想法是

  • 将会话存储引擎从服务器上的文件更改为 数据库
  • 创建一个随机会话id,不要在PHP上中继到 为我生成会话id
  • 更改会话的长度 id设置为允许的最大值(即40个字符)
  • 将新会话id与用户id(应用程序用户标识符,)以及用户的IP地址和用户代理信息一起存储到表中
  • 设置空闲超时,以便系统自动销毁用户 1800秒空闲时间后的会话
  • 在实现上述功能后,在每个请求的页面上,我检查以下内容是否正确

  • 用户浏览器中的有效会话ID
  • 确保我可以将当前IP地址和当前用户代理信息与登录时捕获的信息相匹配
  • 如果会话有效且未过期,则使用它,否则,如果用户_可用,则创建一个新会话(也称为登录尝试)
  • 我看到的问题是,当用户关闭浏览器时,包含会话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, 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();
    }
    

    . 具体看看哪些浏览器没有使cookie过期,哪些用户设置到位。Jared,我的函数是随机的,它使用a-z a-z、减号和逗号。我被告知内置PHP函数将更容易暴力猜测会话ID。此外,关于我代码中的cookie,我将其设置为0过期,这意味着当broswer关闭时过期。与链接Firefox设置类似的Chrome设置是“继续我离开的地方”@MichaelBerkowski我想你说得有道理。非常感谢。你觉得我们班有什么问题吗?我能做些什么来进一步提高安全性?有一个StackExchange网站供代码审查:
    $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();
    }