8

在某种程度上,这个问题可以看作是这个问题的延伸

我们正在考虑发布一个类来处理反序列化和序列化存储在大型生产网站上的表中的会话数据,以便我们可以编辑任意会话数据。

问题是,session_decode()填充当前$_SESSION而不返回解码数组,并且session_encode()不编码给定数组(它只返回当前会话的序列化字符串。)

默认的 PHP 会话序列化处理程序不简单地用于serialize()对会话进行编码,因此,获得相同功能的编码和解码会话的唯一方法是移动全局$_SESSION变量(即存储到会话中、检索数据和恢复) 或通过尝试重现该session.serialize_handler功能的实现。

我们选择了后一种复制方法,因为它似乎不那么具有侵入性。在文档中session_encodesession_decode的评论部分中,已经多次尝试这种复制。我挑选了两个我认为最可靠的并应用它们。decode 方法看起来相当健壮,但 encode 方法虽然有效,但已于 5 年前发布

我们仍然不愿意仅仅因为可能存在看不见的边缘情况会导致这些方法中断而推出它。

最终,我正在寻找:

  • 将破坏以下方法的示例,或
  • 保证这些方法已在生产中使用并且不会破坏
  • 也许已经在生产中尝试和测试过的替代品?

先谢谢大家了!

编码:

class Session extends BaseSession
{
    /**
     * Taken from http://www.php.net/manual/en/function.session-decode.php#108037
     */
    public function unserialized() {
        $session_data = $this->content;
        $method = ini_get("session.serialize_handler");
        switch ($method) {
            case "php":
                return self::unserialize_php($session_data);
                break;
            case "php_binary":
                return self::unserialize_phpbinary($session_data);
                break;
            default:
                throw new Exception("Unsupported session.serialize_handler: " . $method . ". Supported: php, php_binary");
        }
    }

    /**
     * Taken from http://www.php.net/manual/en/function.session-encode.php#76425
     */
    public function serialize($array, $safe = true) {
        // the session is passed as refernece, even if you dont want it to
        if( $safe ) $array = unserialize(serialize( $array )) ;
        $raw = '' ;
        $line = 0 ;
        $keys = array_keys( $array ) ;
        foreach( $keys as $key ) {
            $value = $array[ $key ] ;
            $line ++ ;
            $raw .= $key .'|' ;
            if( is_array( $value ) && isset( $value['huge_recursion_blocker_we_hope'] )) {
                $raw .= 'R:'. $value['huge_recursion_blocker_we_hope'] . ';' ;
            } else {
                $raw .= serialize( $value ) ;
            }
            $array[$key] = Array( 'huge_recursion_blocker_we_hope' => $line ) ;
        }

        $this->content = $raw;
        $this->save();
    }


    private static function unserialize_php($session_data) {
        $return_data = array();
        $offset = 0;
        while ($offset < strlen($session_data)) {
            if (!strstr(substr($session_data, $offset), "|")) {
                throw new Exception("invalid data, remaining: " . substr($session_data, $offset));
            }
            $pos = strpos($session_data, "|", $offset);
            $num = $pos - $offset;
            $varname = substr($session_data, $offset, $num);
            $offset += $num + 1;
            $data = unserialize(substr($session_data, $offset));
            $return_data[$varname] = $data;
            $offset += strlen(serialize($data));
        }
            return $return_data;
    }

    private static function unserialize_phpbinary($session_data) {
        $return_data = array();
        $offset = 0;
        while ($offset < strlen($session_data)) {
            $num = ord($session_data[$offset]);
            $offset += 1;
            $varname = substr($session_data, $offset, $num);
            $offset += $num;
            $data = unserialize(substr($session_data, $offset));
            $return_data[$varname] = $data;
            $offset += strlen(serialize($data));
        }
        return $return_data;
    }
}
4

1 回答 1

1

Igbinary ( https://github.com/igbinary/igbinary/ ) 是标准 php 序列化程序的替代品。igbinary 以紧凑的二进制形式存储 php 数据结构,而不是耗费时间和空间的文本表示。当使用 memcached 或类似的基于内存的存储来存储序列化数据时,节省的费用非常可观。预计存储需求将减少约 50%。具体数字取决于您的数据。

反序列化性能至少与标准 PHP 序列化程序相当。序列化性能取决于启用重复字符串跟踪的“compact_strings”选项。字符串被插入到哈希表中,这增加了一些开销。在通常情况下,这没有太大意义,因为使用模式是“很少序列化,经常反序列化”。使用“compact_strings”选项,igbinary 通常比标准序列化程序慢一点。没有它,会快一点。

特征

  • 支持与标准 PHP 序列化程序相同的数据类型:null、bool、int、float、string、array 和 objects。
  • __autoload&unserialize_callback_func
  • __sleep&__wakeup
  • 可序列化接口
  • 平台之间的数据可移植性(32/64 位,字节序)
  • 在 Linux amd64、Linux ARM、Mac OSX x86、HP-UX PA-RISC 和 NetBSD sparc64 上测试
  • 连接到 APC 操作码缓存作为序列化处理程序 (APC 3.1.7+)
  • 兼容 PHP 5.2 和 5.3

希望能帮助到你

于 2013-03-24T21:04:40.230 回答