浏览器重启后无法从会话中获取数据

时间:2018-07-21 17:43:28

标签: php session

我使用以下 lib 来管理会话,将会话值存储在数据库中,一切正常,我可以getset会话值。

但是重新启动后,我无法获取会话值。 当我尝试使用set会话值时,我会在数据库中创建新行而不是进行更新。

LIB.php

<?php

/**
 * @category    Security
 * @version     1.0
 * @author      First Last 
 * */
class mySessionHandler {

    private $_db = NULL;
    private $_table_name = 'sessions';
    private $_cookie_name = 'session_cookie';
    private $_seconds_till_expiration = 43200; // 2 hours
    private $_renewal_time = 300; // 5 minutes
    private $_expire_on_close = FALSE;
    private $_ip_address = FALSE;
    private $_user_agent = FALSE;
    private $_secure_cookie = FALSE;
    private $_session_id = FALSE;
    private $_data = array();

    public function __construct(array $config) {
        $this->_setConfig($config);
        if ($this->_read()) {
            $this->_update();
        } else {
            $this->_create();
        }
        $this->_cleanExpired();
        $this->_setCookie();
    }

    public function regenerateId() {
        $old_session_id = $this->_session_id;
        $this->_session_id = $this->_generateId();
        $stmt = $this->_db->prepare("UPDATE {$this->_table_name} SET time_updated = ?, session_id = ? WHERE session_id = ?");
        $stmt->execute(array(time(), $this->_session_id, $old_session_id));
        $this->_setCookie();
    }

    public function setData($key, $value) {
        $this->_data[$key] = $value;
        $this->_write();
    }

    public function unsetData($key) {
        if (isset($this->_data[$key])) {
            unset($this->_data[$key]);
        }
    }

    function getData($key) {
        return isset($this->_data[$key]) ? $this->_data[$key] : FALSE;
    }

    public function getAllData() {
        return $this->_data;
    }

    public function destroy() {
        if (isset($this->_session_id)) {
            $stmt = $this->_db->prepare("DELETE FROM {$this->_table_name} WHERE session_id = ?");
            $stmt->execute(array($this->_session_id));
        }
        setcookie($this->_cookie_name, '', time() - 31500000, NULL, NULL, NULL, NULL);
    }

    private function _read() {
        $session_id = filter_input(INPUT_COOKIE, $this->_cookie_name) ? filter_input(INPUT_COOKIE, $this->_cookie_name) : FALSE;
        if (!$session_id) {
            return FALSE;
        }
        $this->_session_id = $session_id;
        $stmt = $this->_db->prepare("SELECT data, time_updated, user_agent, ip_address FROM {$this->_table_name} WHERE session_id = ?");
        $stmt->execute(array($this->_session_id));
        $result = $stmt->fetch(PDO::FETCH_ASSOC);
        if ($result !== FALSE && count($result) > 0) {
            if (!$this->_expire_on_close && (($result['time_updated'] + $this->_seconds_till_expiration) < time())) {
                $this->destroy();
                return FALSE;
            }
            if ($this->_ip_address && ($result['ip_address'] != $this->_ip_address)) {
                $this->_flagForUpdate();
                return FALSE;
            }
            if ($this->_user_agent && ($result['user_agent'] != $this->_user_agent)) {
                $this->_flagForUpdate();
                return FALSE;
            }
            $this->_checkUpdateFlag();
            $this->_checkIdRenewal();
            $user_data = unserialize($result['data']);
            if ($user_data) {
                $this->_data = $user_data;
                unset($user_data);
            }return TRUE;
        }return FALSE;
    }

    private function _create() {
        $this->_session_id = $this->_generateId();
        $stmt = $this->_db->prepare("INSERT INTO {$this->_table_name} (session_id, user_agent, ip_address, time_updated) VALUES (?, ?, ?, ?)");
        $stmt->execute(array($this->_session_id, $this->_user_agent, $this->_ip_address, time()));
    }

    private function _update() {
        $stmt = $this->_db->prepare("UPDATE {$this->_table_name} SET time_updated = ? WHERE session_id = ?");
        $stmt->execute(array(time(), $this->_session_id));
    }

    private function _write() {
        if (count($this->_data) == 0) {
            $custom_data = '';
        } else {
            $custom_data = serialize($this->_data);
        }
        $stmt = $this->_db->prepare("UPDATE {$this->_table_name} SET data = ?, time_updated = ? WHERE session_id = ?");
        $stmt->execute(array($custom_data, time(), $this->_session_id));
    }

    private function _setCookie() {
        setcookie(
                $this->_cookie_name, $this->_session_id, ($this->_expire_on_close) ? 0 : time() + $this->_seconds_till_expiration, // Expiration timestamp
                NULL, NULL, $this->_secure_cookie, // Will cookie be set without HTTPS?
                TRUE // HttpOnly
        );
    }

    private function _cleanExpired() {
        if (mt_rand(1, 1000) == 1) {
            $stmt = $this->_db->prepare("DELETE FROM {$this->_table_name} WHERE (time_updated + {$this->_seconds_till_expiration}) < ?");
            $stmt->execute(array(time()));
        }
    }

    function _generateId() {
        $salt = 'x7^!bo3p,.$$!$6[&Q.#,//@i"%[X';
        $random_number = '9085723012206';
        $random_txt = 'sanoj';
        $ip_address_fragment = md5(substr(filter_input(INPUT_SERVER, 'REMOTE_ADDR'), 0, 5));
        $hash_data = $random_number . $ip_address_fragment . $random_txt . $salt;
        $hash = hash('sha256', $hash_data);
        return $hash;
    }

    private function _checkIdRenewal() {
        $stmt = $this->_db->prepare("SELECT time_updated FROM {$this->_table_name} WHERE session_id = ?");
        $stmt->execute(array($this->_session_id));
        $result = $stmt->fetch(PDO::FETCH_ASSOC);
        if ($result !== FALSE && count($result) > 0) {
            if ((time() - $this->_renewal_time) > $result['time_updated']) {
                $this->regenerateId();
            }
        }
    }

    private function _flagForUpdate() {
        $stmt = $this->_db->prepare("UPDATE {$this->_table_name} SET flagged_for_update = '1' WHERE session_id = ?");
        $stmt->execute(array($this->_session_id));
    }

    private function _checkUpdateFlag() {
        $stmt = $this->_db->prepare("SELECT flagged_for_update FROM {$this->_table_name} WHERE session_id = ?");
        $stmt->execute(array($this->_session_id));
        $result = $stmt->fetch(PDO::FETCH_ASSOC);
        if ($result !== FALSE && count($result) > 0) {
            if ($result['flagged_for_update']) {
                $this->regenerateId();
                $stmt = $this->_db->prepare("UPDATE {$this->_table_name} SET flagged_for_update = '0' WHERE session_id = ?");
                $stmt->execute(array($this->_session_id));
            }
        }
    }

    private function _setConfig(array $config) {
        if (isset($config['database'])) {
            $this->_db = $config['database'];
        } else {
            throw new Exception('Database handle not set!');
        }
        if (isset($config['cookie_name'])) {
            if (!ctype_alnum(str_replace(array('-', '_'), '', $config['cookie_name']))) {
                throw new Exception('Invalid cookie name!');
            } $this->_cookie_name = $config['cookie_name'];
        }
        if (isset($config['table_name'])) {
            if (!ctype_alnum(str_replace(array('-', '_'), '', $config['table_name']))) {
                throw new Exception('Invalid table name!');
            } $this->_table_name = $config['table_name'];
        }
        if (isset($config['seconds_till_expiration'])) {
            if (!is_int($config['seconds_till_expiration']) || !preg_match('#[0-9]#', $config['seconds_till_expiration'])) {
                throw new Exception('Seconds till expiration must be a valid number.');
            }
            if ($config['seconds_till_expiration'] < 1) {
                throw new Exception('Seconds till expiration can not be zero or less. Enable session expiration when the browser closes instead.');
            }
            $this->_seconds_till_expiration = (int) $config['seconds_till_expiration'];
        }
        if (isset($config['expire_on_close'])) {
            if (!is_bool($config['expire_on_close'])) {
                throw new Exception('Expire on close must be either TRUE or FALSE.');
            }
            $this->_expire_on_close = $config['expire_on_close'];
        }
        if (isset($config['renewal_time'])) {
            if (!is_int($config['renewal_time']) || !preg_match('#[0-9]#', $config['renewal_time'])) {
                throw new Exception('Session renewal time must be a valid number.');
            }
            if ($config['renewal_time'] < 1) {
                throw new Exception('Session renewal time can not be zero or less.');
            }
            $this->_renewal_time = (int) $config['renewal_time'];
        }
        if (isset($config['check_ip_address'])) {
            if (!is_string($config['check_ip_address'])) {
                throw new Exception('The IP address must be a string similar to this: \'172.16.254.1\'.');
            }
            if (!preg_match('/^(([1-9]?[0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5]).){3}([1-9]?[0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])$/', $config['check_ip_address'])) {
                throw new Exception('Invalid IP address.');
            }
            $this->_ip_address = $config['check_ip_address'];
        }
        if (isset($config['check_user_agent'])) {
            $this->_user_agent = substr($config['check_user_agent'], 0, 999);
        } if (isset($config['secure_cookie'])) {
            if (!is_bool($config['secure_cookie'])) {
                throw new Exception('The secure cookie option must be either TRUE or FALSE.');
            }
            $this->_secure_cookie = $config['secure_cookie'];
        }
    }

}

即使重新启动浏览器后,如何获取会话值,

GET.PHP

ob_start();
session_start();
include_once('index.php');

echo $session->getData('fname').'<br>';
echo $session->getData('password').'<br>';
echo $session->getData('email').'<br>';

SET.PHP

ob_start();
session_start();
include_once('index.php');

$session->setData('fname', 'first last');
$session->setData('password', '123456');
$session->setData('email', 'first@last.com');
$sesi =  $session->_generateId();
echo $sesi;
$_SESSION['test'] = $sesi;

1 个答案:

答案 0 :(得分:1)

尝试替换_setCookie(),以使您的cookie不会过期

private function _setCookie() {
        setcookie($this->_cookie_name, $this->_session_id, ($this->_expire_on_close) ? 0 : time() + (10 * 365 * 24 * 60 * 60), //Expiration timestamp
                NULL, NULL, $this->_secure_cookie, // Will cookie be set without HTTPS?
                TRUE // HttpOnly
        );
    }