PHP:自定义会话处理程序反序列化在Windows上不起作用 [英] PHP: Custom Session Handler Unserialize Not Working on Windows

查看:61
本文介绍了PHP:自定义会话处理程序反序列化在Windows上不起作用的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我的应用程序的开发环境是Zend Framework 1.11,MSSQL Server 2012,用于与PDO,Windows 7,IIS 7进行数据库连接的SQLSRV扩展.使用自定义会话处理程序类将会话存储在数据库中.

The development environment of my application is Zend Framework 1.11, MSSQL Server 2012, SQLSRV Extension for Database connectivity with PDO, Windows 7, IIS 7. Session is being stored in database by using custom session handler class.

问题是当我在写在Bootstrap.php文件中的session_start()之后打印$ _SESSION时,它没有显示完整的未序列化会话数据数组.会话数据似乎是由会话类处理程序的读取"方法返回的,由于某种原因并未被反序列化.这是我的源代码:-

The issue is that when i print $_SESSION after session_start() which is written in Bootstrap.php file, it does not show complete unserialized array of session data. It seems that session data which is being returned by "read" method of session class handler, not being unserialized for some reason. Here is my source code:-

Bootstrap.php

Bootstrap.php

protected function _initSession() {
    $handler = new Mcd_Core_SessionHandler_Database();

    session_set_save_handler(
        array($handler, 'open'),
        array($handler, 'close'),
        array($handler, 'read'),
        array($handler, 'write'),
        array($handler, 'destroy'),
        array($handler, 'gc')
    );        
    session_start();
    echo "<pre>";
    print_r($_SESSION);
}

SessionHandler类

SessionHandler Class

<?php
class My_Core_SessionHandler_Database
{

    protected $dbh;
    protected $ipAddress = '';

    public function __construct() {   
        $this->dbh = My_Core_Config::get_dbinstance();
    }

    public function open($savePath, $sessionId) {
        return true;
    }

    public function close()  {
        return true;
    }

    public function read($sessionId) {                

        $query = "SELECT TOP 1 CAST(session as varchar(max)) as session
            FROM t_php_session
            WHERE php_session_id = '".$sessionId."'
                AND DATEADD(minute, ".My_Core_Config::get_value('session_timeout_period').", created) >= GETDATE()
                AND user_ip = '".$this->ipAddress."'";

        $stmt = $this->dbh->prepare($query);
        $stmt->execute();
        $result = $stmt->fetchColumn();       

        if ($result === false) {
            return '';
        }
        return $result;
    }

    public function write($sessionId, $sessionData) {
        $query = "
            SELECT id
            FROM t_php_session
            WHERE php_session_id = ?
        ";
        $stmt = $this->dbh->prepare($query);
        $stmt->execute(array($sessionId));
        $result = $stmt->fetchColumn();

        if (empty($result)) {            
            $query = "INSERT INTO t_php_session (php_session_id, session, user_ip, created) VALUES (?, CONVERT(VARBINARY(max), ?), ".$this->ipAddress.", GETDATE())";
            $stmt = $this->dbh->prepare($query);            
            $stmt->execute(array($sessionId, $sessionData));
        } else {
            $query = "
                UPDATE t_php_session
                SET session = CONVERT(VARBINARY(max), ?),
                    user_ip = ".$this->ipAddress.",
                    created = GETDATE()
                WHERE id = ?
            ";
            $stmt = $this->dbh->prepare($query);
            $stmt->execute(array($sessionData, $result));
        }
        return true;
    }

    public function destroy($sessionId) {
        $query = 'DELETE FROM t_php_session WHERE php_session_id = ?';
        $stmt = $this->dbh->prepare($query);
        $stmt->execute(array($sessionId));

        return true;
    }

    public function gc($maxlifetime) {
        $query = "
            DELETE FROM t_php_session
            WHERE DATEADD(minute, ".My_Core_Config::get_value('session_timeout_period').", created) < GETDATE()";

        $stmt = $this->dbh->prepare($query);
        $stmt->execute();

        return true;
    }
}

数据库表中会话字段的数据类型为varbinary(最大值).我只是猜测这可能是问题,但不确定.

The datatype of session field in the database table is varbinary (max). I just guess this might be the issue but not sure.

输出为:

My_Core_Session|a:1:{s:16:"My_Core_Session";a:4:{s:19:"previous_controller";N;s:15:"previous_action";N;s:18:"current_controller";s:16:"authentification";s:14:"current_action";s:5:"login";}}

Bootstrap.php中$ _SESSION的输出是:

Output of $_SESSION in Bootstrap.php is:

Array
(
    [My_Core_Session] => 
)

输出应为:

Array
(
    [My_Core_Session] => Array
        (
            [My_Core_Session] => Array
                (
                    [previous_controller] => 
                    [previous_action] => 
                    [current_controller] => authentification
                    [current_action] => login
                )

        )

)

此应用程序在Linux上可以像相同的数据库一样正常工作,正在使用源代码,但在不同的环境(如Apache 2.2,FreeTDS,Dblib)中使用.我们只是将此应用程序从Linux迁移到Windows并面临此问题.

This application is working fine on Linux as same database, source code is being used but with different environment like Apache 2.2, FreeTDS, Dblib. We just moved this application from Linux to Windows and facing this issue.

推荐答案

我找到了解决方案,并希望与可能面临相同问题的人们分享.问题在于,PHP引擎无法对从MSSQL Server数据库中获取的会话数据进行反序列化,这可能是由于数据带来了一些垃圾.字段(保存会话的位置)的数据类型为 varbinary(max).我只是将其更改为 varchar(max)以查看其是否有效,并且::

I found the solution and would like to share it with those people who may face the same problem. The issue was that PHP engine was not able to deserialize the session data that was being fetched from MSSQL Server database may be some garbage was coming along with the data. The data type of the field (where session was being saved) was varbinary (max). I simply changed it to varchar (max) to see if it works and it worked :)

这是一个特定的用例,其中自定义会话处理程序在带有MSSQL Server数据库的zend框架中使用.幸运的是,它现在已解决:)

This is a specific use case where custom session handler was used in zend framework with MSSQL Server database. Luckily, it is resolved now :)

祝你好运!

这篇关于PHP:自定义会话处理程序反序列化在Windows上不起作用的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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