如何将会话数据反序列化为PHP中的任意变量?

时间:2009-02-10 01:21:16

标签: php session serialization

我想将session_encode() d个会话数据串反序列化到我自己的数组(即不到$_SESSION。)

似乎没有内置函数来处理这个问题。有session_decode(),但它直接写入$_SESSION超全局。有unserialize()但它在session_encode()'字符串上返回false,因为它们的格式略有不同。

最好的方法是什么?

编辑:这是我使用的代码:http://us.php.net/manual/en/function.session-decode.php#79244

7 个答案:

答案 0 :(得分:18)

我注意到用于手动解码会话的已发布解决方案(在php.net上)并不完美,因此我提供了更强大的解决方案。

preg_match解决方案永远无法工作。找到一个可能会破坏反序列化的案例并不难。 在jason-joeymail的情况下休息:

$_SESSION["test"] = ";oops|";

您可以在下面找到我的解决方案。它不使用正则表达式,而是使用序列化操作的可逆性,并且序列化的“特征”在认为已完成时忽略所有进一步的输入。它绝不是一个美观或特别快的解决方案,但它是一个更强大的解决方案。 我为“php”和“php_binary”添加了一个反序列化器。为“wddx”添加一个应该是微不足道的。

class Session {
    public static function unserialize($session_data) {
        $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");
        }
    }

    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;
    }
}

用法:

Session::unserialize(session_encode());

答案 1 :(得分:7)

查看PHP手册session_decode页面中的注释。它有一堆用户函数来手动解码session_encode字符串。据我所知,这是唯一的出路。

答案 2 :(得分:2)

上面的自定义'php'反序列化函数可以通过避免“递增偏移”方法而变得更干净,而有利于逐渐占用输入会话字符串。

我没有检查它在速度方面的比较,但它肯定更整洁(并且在while循环中保存了对strlen的重复调用)

$r = array();
while ($i = strpos($str, '|'))
{
    $k = substr($str, 0, $i);
    $v = unserialize(substr($str, 1 + $i));
    $str = substr($str, 1 + $i + strlen(serialize($v)));
    $r[$k] = $v;
}
return $r; // session data are now in a normal array

答案 3 :(得分:1)

这对我有用:

/* storre current session */
$current_session = session_encode(); 

/* extract $other_user_session from file or database,
   into the $_SESSION global variable */
session_decode($other_user_session); 

/* use the other user session data:  $something = $_SESSION['something']; */

/* restore previous sesison info */
session_decode($current_session); /* current $_SESSION restored */

答案 4 :(得分:1)

根据http://php.net/manual/session.configuration.php#ini.session.serialize-handler,您可以设置

session.serialize_handler = php_serialize

然后你可以使用php的serialize()/ unserialize()函数。

答案 5 :(得分:0)

function data_session_decode($data){
    $data = array_filter(explode(';',$data));
    $list_data = array();
    foreach($data as $key => $dat){
        if(!empty($dat)){
          $data[$key] = array_filter(explode('|',$dat));
          if(substr($data[$key][1], 0, 1) == 'i'){
              $list_data[$data[$key][0]] = strstr($data[$key][1], ':');
              $list_data[$data[$key][0]] = substr($list_data[$data[$key][0]], 1);
          }elseif(substr($data[$key][1], 0, 1) == 's'){
              $list_data[$data[$key][0]] = strstr($data[$key][1], '"');
              $list_data[$data[$key][0]] = substr($list_data[$data[$key][0]], 0, -1);
              $list_data[$data[$key][0]] = substr($list_data[$data[$key][0]], 1);
          }else{
              unset($data[$key]);
          }
        }
    }
    unset($data);
    return $list_data;
}

// HERE DATA SESSION EX:

$ dataSession ='user_name | s:8:“你的名字”;日期| i:1459396063';

//停止

的print_r($这 - &GT; data_session_decode($ DATASESSION));

答案 6 :(得分:-9)

你为什么不这样做呢?

$myVariable = serialize($_SESSION);
$sessionCopy = unserialize($myVariable);
祝你好运!