我注意到手动解码会话的已发布解决方案(在 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());