PHP生成”;Ghost";会话表中的会话


PHP Generating "Ghost" sessions in the sessions table

  • Windows版本:Win 8 64位
  • WAMP版本:2.5 64位
  • PHP版本:5.5.12

PHP正在会话表中为每个页面请求生成我不得不称之为"ghost"的会话。最奇怪的是,只需点击浏览器窗口似乎就足以创建一个新会话。它发生在Firefox和Chrome中(从未在Chrome中安装任何扩展/插件(,但在IE11中没有发生。

在这一点上,我不知道是Firefox和Chrome处理cookie的方式出现了错误,还是PHP出现了错误。我正在测试的代码如下(包括测试表的SHOW CREATE TABLE(。

<?php
error_reporting(E_ALL | E_STRICT | E_ERROR | E_WARNING | E_PARSE | E_NOTICE | E_CORE_ERROR | E_CORE_WARNING | E_COMPILE_ERROR | E_COMPILE_WARNING | E_USER_ERROR | E_USER_WARNING | E_USER_NOTICE | E_RECOVERABLE_ERROR);
$db_type = 'mysql';
$db_host = 'local_host';
$dsn = 'mysql:dbname=test;host=localhost';
$user = 'sess_test_user';
$password = 'password';
try {
    $db = new PDO($dsn, $user, $password);
// Create a new instance of PDO (connect to the database)
}
catch(Exception $e) {
    die('Failed To Connect To Database');
}
class db_session_handler implements SessionHandlerInterface {
    public function __construct($db) {
        $this->db = $db;
    }
    public function open($save_path,$session_name) {
        $this->db;
        return true;
    }
    public function close() {
        unset($this->db);
        return true;
    }
    public function read($session_id) {
        try {
            $sql="
                SELECT
                    sess_data
                FROM
                    session_table
                WHERE
                    sess_id = :sess_id
            ";
            $stmt = $this->db->prepare($sql);
            $stmt->bindParam(':sess_id', $session_id);
            $stmt->execute();
            $res = $stmt->fetchAll(PDO::FETCH_ASSOC);
            if (count($res) <> 1 ) {
                return false;
            } else {
                return $res[0]['sess_data'];
            }
        }
        catch (PDOException $e) {
            return false;
        }
    }
    public function write($session_id,$session_data) {      
        try {
            $sql="
                SELECT
                    sess_data
                FROM
                    session_table
                WHERE
                    sess_id = :sess_id
            ";
            $stmt = $this->db->prepare($sql);
            $stmt->bindParam(':sess_id', $session_id);
            $stmt->execute();
            $res = $stmt->fetchAll(PDO::FETCH_ASSOC);
        }
        catch (PDOException $e) {
            return false;
        }
        try {
            if (count($res) === 0) {
                $sql="
                INSERT INTO
                    session_table
                (
                      sess_id
                    , user
                    , start
                    , last_activity
                    , expires
                    , sess_data
                )
                VALUES
                    (
                          :sess_id
                        , '0'
                        , NOW()
                        , NOW()
                        , DATE_ADD(NOW(), INTERVAL 30 MINUTE)
                        , :sess_data                        
                    )               
                ";
                $stmt->bindParam(':sess_id', $session_id);
                $stmt->bindParam(':sess_data', $session_data);
            } else {
                $sql="
                    UPDATE
                        session_table
                    SET
                          last_activity = NOW()
                        , expires = DATE_ADD(NOW(), INTERVAL 30 MINUTE)
                        , sess_data = :sess_data
                    WHERE
                        sess_id = :sess_id              
                ";
            }
            $stmt = $this->db->prepare($sql);
            $stmt->bindParam(':sess_id', $session_id);
            $stmt->bindParam(':sess_data', $session_data);
            $stmt->execute();
            return true;
        }
        catch (PDOException $e) {
            return false;
        }
    }
    public function destroy($session_id) {
        try {
            $sql="
                DELETE FROM
                    session_table
                WHERE
                    sess_id = :sess_id
            ";
            $stmt = $this->db->prepare($sql);
            $stmt->bindParam(':sess_id', $session_id);
            $stmt->execute();
            return true;
        }
        catch (PDOException $e) {
            return false;
        }
    }
    public function gc($max_lifetime) {
        try {
            $sql="
                DELETE FROM
                    session_table
                WHERE
                    last_activity < expires
            ";
            $stmt = $this->db->prepare($sql);
            $stmt->execute();
        }
        catch (PDOException $e) {
            return false;
        }
    }
    public function __destruct() {
        session_write_close();
    }
}
$db_session_handler = new db_session_handler($db);
session_set_save_handler($db_session_handler,true);
session_start();
echo session_id();
echo "
CREATE TABLE IF NOT EXISTS `session_table` (
  `sess_id` varchar(255) CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL,
  `user` int(11) NOT NULL,
  `start` datetime NOT NULL,
  `last_activity` datetime NOT NULL,
  `expires` datetime NOT NULL,
  `sess_data` varchar(255) CHARACTER SET utf8 COLLATE utf8_unicode_ci NOT NULL,
  PRIMARY KEY (`sess_id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin;
";      
?>

看起来FireFox和Chrome是罪魁祸首,在完全卸载它们并重新安装后,问题已经消失,所以可能每个中的某些东西都在某个时候损坏了