PHP 自定义会话处理程序问题 (PHP 7.1) [英] PHP Custom Session Handler Problems (PHP 7.1)

查看:39
本文介绍了PHP 自定义会话处理程序问题 (PHP 7.1)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我刚刚在计算机上从 PHP 7.0 迁移到 PHP 7.1(WAMP 当前版本的全新/全新安装),它似乎破坏了自定义会话处理程序中应该将会话保存到数据库的某些内容而不是使用文件系统.

自定义处理程序类是:

class db_session_handler 实现了 SessionHandlerInterface {公共函数 __construct($db) {$this->db = $db;}公共函数打开($save_path,$session_name){$this->db;返回真;}公共函数关闭(){未设置($this->db);返回真;}公共函数读($session_id){如果 (!isset($session_id)) {$session_id='';}尝试 {$sql="选择sess_data从ue_user_session在哪里sess_id = :sess_id";$stmt = $this->db->prepare($sql);$stmt->bindParam(':sess_id', $session_id);$stmt->execute();$res = $stmt->fetchAll(PDO::FETCH_ASSOC);如果(计数($res)<> 1){返回假;} 别的 {返回 $res[0]['sess_data'];}}捕获(PDOException $e){error_log('session读取方法读取session数据表出错',3,"C:\wamp\www\universal_empires\test_log.txt");error_log(" 查询出错:$sql",3,"C:\wamp\www\universal_empires\test_log.txt");error_log("给出原因:$e->getMessage()",3,"C:\wamp\www\universal_empires\test_log.txt");返回假;}}公共函数写($session_id,$session_data){尝试 {$sql="选择sess_data从ue_user_session在哪里sess_id = :sess_id";$stmt = $this->db->prepare($sql);$stmt->bindParam(':sess_id', $session_id);$stmt->execute();$res = $stmt->fetchAll(PDO::FETCH_ASSOC);}捕获(PDOException $e){error_log('session读取方法读取session数据表出错',3,"C:\wamp\www\universal_empires\test_log.txt");error_log(" 查询出错:$sql",3,"C:\wamp\www\universal_empires\test_log.txt");error_log("给出原因:$e->getMessage()",3,"C:\wamp\www\universal_empires\test_log.txt");返回假;}$ip = get_ip();如果(isset($_SESSION['user_id'])){$user_id = (int) $_SESSION['user_id'];} 别的 {$user_id= (int) 0;}如果(空($res)){如果 (!isset($_SERVER['REDIRECT_URL'])) {$location = '未知';} 别的 {$location = $_SERVER['REDIRECT_URL'];}尝试 {如果(计数($res)=== 0){$sql="插入ue_user_session(sess_id, 用户, 开始, last_activity, 地点, ip, 用户代理, 用户主机, 用户语言, 过期, sess_data)价值观(:sess_id, 0, 现在(), 现在(), :地点, :ip, :用户代理, :user_host, :user_lang, DATE_ADD(NOW(), 间隔 30 分钟), :sess_data)";$stmt = $this->db->prepare($sql);$stmt->bindParam(':sess_id', $session_id);$stmt->bindParam(':location', $location);$stmt->bindParam(':ip', $ip);$stmt->bindParam(':user_agent', $_SERVER['HTTP_USER_AGENT']);$stmt->bindParam(':user_host', $_SERVER['REMOTE_HOST']);$stmt->bindParam(':user_lang', $_SERVER['HTTP_ACCEPT_LANGUAGE']);$stmt->bindParam(':sess_data', $session_data);$stmt->execute();返回真;}}捕获(PDOException $e){error_log('session读取方法读取session数据表出错',3,"C:\wamp\www\universal_empires\test_log.txt");error_log(" 查询出错:$sql",3,"C:\wamp\www\universal_empires\test_log.txt");error_log("给出原因:$e->getMessage()",3,"C:\wamp\www\universal_empires\test_log.txt");返回假;}} 别的 {尝试 {$sql="更新用户名放last_activity = 现在()在哪里id = :user_id";$stmt = $this->db->prepare($sql);$stmt->bindParam(':user_id', $user_id);$stmt->execute();}捕获(PDOException $e){error_log('session读取方法读取session数据表出错',3,"C:\wamp\www\universal_empires\test_log.txt");error_log(" 查询出错:$sql",3,"C:\wamp\www\universal_empires\test_log.txt");error_log("给出原因:$e->getMessage()",3,"C:\wamp\www\universal_empires\test_log.txt");返回假;}如果 (!isset($_SERVER['REDIRECT_URL'])) {$location = '未知';} 别的 {$location = $_SERVER['REDIRECT_URL'];}尝试 {$sql="更新ue_user_session放last_activity = 现在(), 过期 = DATE_ADD(NOW(), INTERVAL 30 MINUTE), 位置 = :位置, ip = :ip, user_agent = :user_agent, user_host = :user_host, user_language = :user_lang, sess_data = :sess_data, 用户 = :user_id在哪里sess_id = :sess_id";$stmt = $this->db->prepare($sql);$stmt->bindParam(':location', $location);$stmt->bindParam(':ip', $ip);$stmt->bindParam(':user_agent', $_SERVER['HTTP_USER_AGENT']);$stmt->bindParam(':user_host', $_SERVER['REMOTE_HOST']);$stmt->bindParam(':user_lang', $_SERVER['HTTP_ACCEPT_LANGUAGE']);$stmt->bindParam(':sess_data', $session_data);$stmt->bindParam(':user_id', $user_id);$stmt->bindParam(':sess_id', $session_id);$stmt->execute();返回真;}捕获(PDOException $e){error_log('session读取方法读取session数据表出错',3,"C:\wamp\www\universal_empires\test_log.txt");error_log(" 查询出错:$sql",3,"C:\wamp\www\universal_empires\test_log.txt");error_log("给出原因:$e->getMessage()",3,"C:\wamp\www\universal_empires\test_log.txt");返回假;}}$this->gc();}公共函数销毁($session_id){尝试 {$sql="删除自ue_user_session在哪里sess_id = :sess_id";$stmt = $this->db->prepare($sql);$stmt->bindParam(':sess_id', $session_id);$stmt->execute();返回真;}捕获(PDOException $e){error_log('session读取方法读取session数据表出错',3,"C:\wamp\www\universal_empires\test_log.txt");error_log(" 查询出错:$sql",3,"C:\wamp\www\universal_empires\test_log.txt");error_log("给出原因:$e->getMessage()",3,"C:\wamp\www\universal_empires\test_log.txt");返回假;}}公共函数 gc($max_lifetime) {尝试 {$sql="删除自ue_user_session在哪里现在()>过期";$stmt = $this->db->prepare($sql);$stmt->execute();返回真;}捕获(PDOException $e){error_log('session读取方法读取session数据表出错',3,"C:\wamp\www\universal_empires\test_log.txt");error_log(" 查询出错:$sql",3,"C:\wamp\www\universal_empires\test_log.txt");error_log("给出原因:$e->getMessage()",3,"C:\wamp\www\universal_empires\test_log.txt");返回假;}}}

它的初始化:

ini_set('session.use_only_cookies', 1);$db_session_handler = 新的 db_session_handler($db);session_set_save_handler($db_session_handler,真);if (session_start() === false ) {die('会话处理程序损坏了!!!!');}

阅读 session_set_save_handler() 的手册页,我找不到任何可以解释我得到的错误的地方:

<块引用>

警告:session_start():无法读取会话数据:第 36 行 C:\wamp\www\universal_empires\libs\bootstrap.php 中的用户(路径:c:/wamp/tmp)

该文件中的第 36 行是对 session_start() 的调用.

搜索我能找到的唯一修复是特定于给定框架的.我需要知道是什么导致 session_start() 失败(从阅读更改 7.1 session_start() 返回 false 而不是在出现问题时尝试继续前进.

我的猜测是 7.1 中发生了一些变化,在 7.0 中可能允许继续进行,但在 7.1 中无论出现什么问题都更加严格,并且使 session_start() 返回 false.

我已经清空了数据库中的会话表并检查了基于文件的会话的存储位置.唯一存在的基于文件的"会话文件是 PHPMyAdmin.

有谁知道它在 PHP 7.1 中发生了什么而在 PHP 7.0 中没有发生冲突?

解决方案

罪魁祸首已找到.事实证明 session_start() 不喜欢自定义会话处理程序的 read 方法,如果不存在会话则返回 false .如果其他人遇到类似问题,如果您不存在会话,则 read 方法需要返回一个空字符串,而不是 false 或 null.

该解决方案位于 http://php.net/manual/en/function.session-start.php#120589 我正在查看 session_set_save_handler() 的手册页,没想到解决方案实际上位于 session_start() 页面的评论部分.

我不知道为什么要对 session_start() 方法期望从自定义会话处理程序的 read 方法获得的内容进行更改

I've just migrated from PHP 7.0 to PHP 7.1 (fresh/clean install of the current version of WAMP) on a computer and it seems to have broken something in the custom session handler that's supposed to save the session to the database instead of using the file system.

The custom hander class is:

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) {

        if (!isset($session_id)) {
            $session_id='';
        }

        try {
            $sql="
                SELECT
                    sess_data
                FROM
                    ue_user_session
                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) {
            error_log('Error reading the session data table in the session reading method.',3,"C:\wamp\www\universal_empires\test_log.txt");
            error_log(" Query with error: $sql",3,"C:\wamp\www\universal_empires\test_log.txt");
            error_log(" Reason given: $e->getMessage()",3,"C:\wamp\www\universal_empires\test_log.txt");
            return false;
        }
    }

    public function write($session_id,$session_data) {

        try {
            $sql="
                SELECT
                    sess_data
                FROM
                    ue_user_session
                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) {
            error_log('Error reading the session data table in the session reading method.',3,"C:\wamp\www\universal_empires\test_log.txt");
            error_log(" Query with error: $sql",3,"C:\wamp\www\universal_empires\test_log.txt");
            error_log(" Reason given: $e->getMessage()",3,"C:\wamp\www\universal_empires\test_log.txt");
            return false;
        }
        $ip = get_ip();
        if (isset($_SESSION['user_id'])) {
            $user_id = (int) $_SESSION['user_id'];
        } else {
            $user_id= (int) 0;
        }       
        if (empty($res)) {

            if (!isset($_SERVER['REDIRECT_URL'])) {
                $location = 'Unknown';
            } else {
                $location = $_SERVER['REDIRECT_URL'];
            }

            try {
                if (count($res) === 0) {
                    $sql="
                        INSERT INTO
                            ue_user_session
                        (
                              sess_id
                            , user
                            , start
                            , last_activity
                            , location
                            , ip
                            , user_agent
                            , user_host
                            , user_language
                            , expires
                            , sess_data
                        )
                        VALUES
                            (
                                  :sess_id
                                , 0
                                , NOW()
                                , NOW()
                                , :location
                                , :ip
                                , :user_agent
                                , :user_host
                                , :user_lang
                                , DATE_ADD(NOW(), INTERVAL 30 MINUTE)
                                , :sess_data                        
                            )               
                    ";

                    $stmt = $this->db->prepare($sql);
                    $stmt->bindParam(':sess_id', $session_id);
                    $stmt->bindParam(':location', $location);
                    $stmt->bindParam(':ip', $ip);
                    $stmt->bindParam(':user_agent', $_SERVER['HTTP_USER_AGENT']);
                    $stmt->bindParam(':user_host', $_SERVER['REMOTE_HOST']);
                    $stmt->bindParam(':user_lang', $_SERVER['HTTP_ACCEPT_LANGUAGE']);
                    $stmt->bindParam(':sess_data', $session_data);
                    $stmt->execute();
                    return true;
                }
            }
            catch (PDOException $e) {
                error_log('Error reading the session data table in the session reading method.',3,"C:\wamp\www\universal_empires\test_log.txt");
                error_log(" Query with error: $sql",3,"C:\wamp\www\universal_empires\test_log.txt");
                error_log(" Reason given: $e->getMessage()",3,"C:\wamp\www\universal_empires\test_log.txt");
                return false;
            }
        } else {

            try {
                $sql="
                    UPDATE
                        ue_user
                    SET
                        last_activity = NOW()
                    WHERE
                        id =  :user_id
                ";
                $stmt = $this->db->prepare($sql);
                $stmt->bindParam(':user_id', $user_id);
                $stmt->execute();
            }
            catch (PDOException $e) {
                error_log('Error reading the session data table in the session reading method.',3,"C:\wamp\www\universal_empires\test_log.txt");
                error_log(" Query with error: $sql",3,"C:\wamp\www\universal_empires\test_log.txt");
                error_log(" Reason given: $e->getMessage()",3,"C:\wamp\www\universal_empires\test_log.txt");
                return false;
            }


            if (!isset($_SERVER['REDIRECT_URL'])) {
                $location = 'Unknown';
            } else {
                $location = $_SERVER['REDIRECT_URL'];
            }
            try {

                $sql="
                    UPDATE
                        ue_user_session
                    SET
                          last_activity = NOW()
                        , expires = DATE_ADD(NOW(), INTERVAL 30 MINUTE)
                        , location = :location
                        , ip = :ip
                        , user_agent = :user_agent
                        , user_host = :user_host
                        , user_language = :user_lang
                        , sess_data = :sess_data
                        , user = :user_id
                    WHERE
                        sess_id = :sess_id              
                ";

                $stmt = $this->db->prepare($sql);
                $stmt->bindParam(':location', $location);
                $stmt->bindParam(':ip', $ip);
                $stmt->bindParam(':user_agent', $_SERVER['HTTP_USER_AGENT']);
                $stmt->bindParam(':user_host', $_SERVER['REMOTE_HOST']);
                $stmt->bindParam(':user_lang', $_SERVER['HTTP_ACCEPT_LANGUAGE']);
                $stmt->bindParam(':sess_data', $session_data);
                $stmt->bindParam(':user_id', $user_id);
                $stmt->bindParam(':sess_id', $session_id);
                $stmt->execute();
                return true;
            }
            catch (PDOException $e) {
                error_log('Error reading the session data table in the session reading method.',3,"C:\wamp\www\universal_empires\test_log.txt");
                error_log(" Query with error: $sql",3,"C:\wamp\www\universal_empires\test_log.txt");
                error_log(" Reason given: $e->getMessage()",3,"C:\wamp\www\universal_empires\test_log.txt");
                return false;
            }
        }
        $this->gc();
    }

    public function destroy($session_id) {
        try {
            $sql="
                DELETE FROM
                    ue_user_session
                WHERE
                    sess_id = :sess_id
            ";
            $stmt = $this->db->prepare($sql);
            $stmt->bindParam(':sess_id', $session_id);
            $stmt->execute();
            return true;
        }
        catch (PDOException $e) {
            error_log('Error reading the session data table in the session reading method.',3,"C:\wamp\www\universal_empires\test_log.txt");
            error_log(" Query with error: $sql",3,"C:\wamp\www\universal_empires\test_log.txt");
            error_log(" Reason given: $e->getMessage()",3,"C:\wamp\www\universal_empires\test_log.txt");
            return false;
        }
    }

    public function gc($max_lifetime) {
        try {
            $sql="
                DELETE FROM
                    ue_user_session
                WHERE
                    NOW() > expires
            ";
            $stmt = $this->db->prepare($sql);
            $stmt->execute();
            return true;
        }
        catch (PDOException $e) {
            error_log('Error reading the session data table in the session reading method.',3,"C:\wamp\www\universal_empires\test_log.txt");
            error_log(" Query with error: $sql",3,"C:\wamp\www\universal_empires\test_log.txt");
            error_log(" Reason given: $e->getMessage()",3,"C:\wamp\www\universal_empires\test_log.txt");
            return false;
        }
    }
}

It's initilised by:

ini_set('session.use_only_cookies', 1);

$db_session_handler = new db_session_handler($db);
session_set_save_handler($db_session_handler, true);

if (session_start() === false ) {
    die('The Session Handler Is Broken!!!!');
}

Reading through the manual page for session_set_save_handler() I can't spot anything mentioned that might explain the error that I'm getting which is:

Warning: session_start(): Failed to read session data: user (path: c:/wamp/tmp) in C:\wamp\www\universal_empires\libs\bootstrap.php on line 36

Line 36 in that file is the call to session_start().

Googling around the only fixes that I can find are specific to a given framework. What I need to know is what's causing session_start() to fail (from reading about changes to 7.1 session_start() returns false instead of trying to plod on when something's not right.

My guess is that something has changed in 7.1 where in 7.0 possibly it was allowed to carry on but in 7.1 it's more stricter with whatever the problem is and makes session_start() return false.

I've emptied the sessions table in the database and have checked where file-based sessions get stored. The only "file-based" session file present is PHPMyAdmin.

Does anyone know what it's falling foul of in PHP 7.1 that it doesn't fall foul of in PHP 7.0?

解决方案

Culprit has been found. It turns out that session_start() doesn't like the read method of a custom session handler returning false if there's no session in existence. if anyone else gets a similar problem, if you've no session in existence, then the read method needs to return an empty string instead of either false or null.

The solution was found at http://php.net/manual/en/function.session-start.php#120589 i was looking at the the manual page for session_set_save_handler(), not expecting the solution to actually be in the comments section of the session_start() page.

I don't know why the change was made to what the session_start() method expects to get from the read method of a custom session handler

这篇关于PHP 自定义会话处理程序问题 (PHP 7.1)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆