在某种程度上,这个问题可以看作是这个问题的延伸。
我们正在考虑发布一个类来处理反序列化和序列化存储在大型生产网站上的表中的会话数据,以便我们可以编辑任意会话数据。
问题是,session_decode()
填充当前$_SESSION
而不返回解码数组,并且session_encode()
不编码给定数组(它只返回当前会话的序列化字符串。)
默认的 PHP 会话序列化处理程序不简单地用于serialize()
对会话进行编码,因此,获得相同功能的编码和解码会话的唯一方法是移动全局$_SESSION
变量(即存储到会话中、检索数据和恢复) 或通过尝试重现该session.serialize_handler
功能的实现。
我们选择了后一种复制方法,因为它似乎不那么具有侵入性。在文档中session_encode和session_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;
}
}