【问题标题】:Custom serialize_handler for custom php SessionHandler (DB storage)自定义 php SessionHandler(数据库存储)的自定义 serialize_handler
【发布时间】:2012-04-14 10:42:16
【问题描述】:

在 php 中使用 3rd 方 (django) 会话管理的过程中,我需要有 自定义序列化函数 以便对其进行正确编码/解码,以适应 django 对会话数据的加盐存储。目前看来ini设置session.serialize_handler可以是php也可以是wddx。

有没有办法将自定义的 serialize_handler 设置为一个类?

我想要这样的东西:

class CustomSessionSerializer {

    public static function serialize($data){
    // Serializes raw data
    }

    public static function unserialize($sdata){
    // Deserializes serialized data
    }
}

让我的自定义 SessionHandler 使用它。

igbinary project on github 似乎添加了一个自定义 serialize_handler 作为 php 扩展。 我很好奇自定义序列化是否不能在其他地方发生,而不是作为 C 扩展。

【问题讨论】:

  • github 上的 igbinary 项目 (github.com/igbinary/igbinary) 似乎实现了自定义序列化,但这远远超出了我对 php 自定义的预期。
  • 我认为用普通的 PHP 是不可能的,除非你接管整个 $_SESSION 超全局并自己编写所有与会话相关的内容。

标签: php session serialization


【解决方案1】:

我一直在处理这个问题,并且有一个解决方案。

这个想法是,虽然您可以轻松地从 PHP 修改 session.serializer_handler,但您可以在运行序列化程序之前清空 $ _SESSION 的内容。
使用一个管理会话的类(如 Zend\Session\SessionManager),其中注册了register_shutdown_function 一个函数,其中将save_handler 传递回$ _SESSION 内容的副本然后$ _SESSION 为空。

这样序列化程序会在空字符串上运行,并且自定义序列化会在您的自定义 save_handler 上执行。

【讨论】:

    【解决方案2】:

    你可以使用session_set_save_handler()来使用你自己的会话处理函数

    在 PHP 5.4 中,您可以使用 SessionHandlerInterface

    默认情况下,您将收到已经序列化的数据,因此您必须取消序列化并使用自己的序列化例程。

    【讨论】:

    • 破解,如果你仔细看看我的问题,你会发现我已经设置了一个自定义会话处理程序。问题是关于自定义序列化,因为这一步发生在读取之前和写入之后。
    • 你只剩下 session.serialize_handler 让你做的事情(普通或使用 PHP 扩展),或者使用 readwrite 处理程序并进行自定义反序列化 -> PHP 序列化 / PHP 反序列化 - > 在其中自定义序列化。
    【解决方案3】:

    可能看起来像是一种解决方法,但它可以满足您的需求。当您的自定义会话处理程序接收到 $_SESSION 超全局并且您需要从读取处理程序将其作为序列化返回时,将应用序列化。但是,您可以将会话存储为任何序列化或格式或任何您想要的。

    例子

    class SessionHandler {
    
        public function __construct() {
           session_set_save_handler(
                array($this, 'open')
               ,array($this, 'close')
               ,array($this, 'read')
               ,array($this, 'write')
               ,array($this, 'destroy')
               ,array($this, 'gc')
            );
        }
    
        public function open($savePath, $sessionName) {
            return true;
        }
    
        public function close() {
            return true;
        }
    
        public function read($id) {
            $data = CustomStorage::fetchSessionData($id);
            return serialize(
                CustomSerialization::unserialize($data);
            );
        }
    
        public function write($id, $serializedData) {
            CustomStorage::writeSessionData(
                 $id
                ,CustomSerialization::serialize(unserialize($serializedData))
            );
            return true;
        }
    
        //gc and destroy
    }
    

    虽然不漂亮而且有点开销,但你只需要在存储时控制序列化,所以它应该可以解决问题。

    希望对你有帮助!

    【讨论】:

    • 感谢 capi,不幸的是,看起来奇怪的序列化是在调用 session_encode 时发生的,在我看来这一步不能取消
    猜你喜欢
    • 2018-04-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-01-04
    • 2014-11-30
    • 2013-02-17
    • 2020-06-12
    • 1970-01-01
    相关资源
    最近更新 更多