What to do if php deserialization fails

藏色散人
Release: 2023-03-05 21:22:01
Original
3557 people have browsed it

php反序列化失败是因为序列化数据时的编码与反序列化时的编码不一致导致的,其解决办法就是使用处理过的单双引号,过滤“\r”的“mb_unserialize”方法即可成功反序列化。

What to do if php deserialization fails

推荐:《PHP视频教程

php unserialize 返回false的解决方法

php 提供serialize(序列化) 与unserialize(反序列化)方法。

使用serialize序列化后,再使用unserialize反序列化就可以获取原来的数据。

<?php
$arr = array(
    &#39;name&#39; => &#39;fdipzone&#39;,
    &#39;gender&#39; => &#39;male&#39;
);

$str = serialize($arr); //序列化
echo &#39;serialize str:&#39;.$str."\r\n\r\n";

$content = unserialize($str); // 反序列化
echo "unserialize str:\r\n";
var_dump($content);
?>
Copy after login

输出:

serialize str:a:2:{s:4:"name";s:8:"fdipzone";s:6:"gender";s:4:"male";}

unserialize str:
array(2) {
  ["name"]=>
  string(8) "fdipzone"
  ["gender"]=>
  string(4) "male"
}
Copy after login

但下面这个例子反序列化会返回false

<?php
$str = &#39;a:9:{s:4:"time";i:1405306402;s:4:"name";s:6:"新晨";s:5:"url";s:1:"-";s:4:"word";s:1:"-";s:5:"rpage";s:29:"http://www.baidu.com/test.html";s:5:"cpage";s:1:"-";s:2:"ip";s:15:"117.151.180.150";s:7:"ip_city";s:31:"中国北京市 北京市移动";s:4:"miao";s:1:"5";}&#39;;
var_dump(unserialize($str)); // bool(false)
?>
Copy after login

检查序列化后的字符串,发现出问题是在两处地方

s:5:"url"

s:29:"http://www.baidu.com/test.html"

这两处应为

s:3:"url"

s:30:"http://www.baidu.com/test.html"

出现这种问题的原因是序列化数据时的编码与反序列化时的编码不一致导致,例如数据库是latin1和UTF-8字符长度不一样。

另外有可能出问题的还有单双引号,ascii字符"\0"被解析为 '\0',\0在C中是字符串的结束符等于chr(0),错误解析后算了2个字符。

\r在计算长度时也会出问题。

解决方法如下:

// utf8
function mb_unserialize($serial_str) {
    $serial_str= preg_replace(&#39;!s:(\d+):"(.*?)";!se&#39;, "&#39;s:&#39;.strlen(&#39;$2&#39;).&#39;:\"$2\";&#39;", $serial_str );
    $serial_str= str_replace("\r", "", $serial_str);
    return unserialize($serial_str);
}

// ascii
function asc_unserialize($serial_str) {
    $serial_str = preg_replace(&#39;!s:(\d+):"(.*?)";!se&#39;, &#39;"s:".strlen("$2").":\"$2\";"&#39;, $serial_str );
    $serial_str= str_replace("\r", "", $serial_str);
    return unserialize($serial_str);
}
Copy after login

例子:

echo &#39;<meta http-equiv="content-type" content="text/html; charset=utf-8">&#39;;

// utf8
function mb_unserialize($serial_str) {
    $serial_str= preg_replace(&#39;!s:(\d+):"(.*?)";!se&#39;, "&#39;s:&#39;.strlen(&#39;$2&#39;).&#39;:\"$2\";&#39;", $serial_str );
    $serial_str= str_replace("\r", "", $serial_str);
    return unserialize($serial_str);
}

$str = &#39;a:9:{s:4:"time";i:1405306402;s:4:"name";s:6:"新晨";s:5:"url";s:1:"-";s:4:"word";s:1:"-";s:5:"rpage";s:29:"http://www.baidu.com/test.html";s:5:"cpage";s:1:"-";s:2:"ip";s:15:"117.151.180.150";s:7:"ip_city";s:31:"中国北京市 北京市移动";s:4:"miao";s:1:"5";}&#39;;

var_dump(unserialize($str));    // false

var_dump(mb_unserialize($str)); // 正确
Copy after login

使用处理过单双引号,过滤\r的mb_unserialize方法就能成功反序列化了。

使用unserialize
bool(false)

使用mb_unserialize
array(9) {
  ["time"]=>
  int(1405306402)
  ["name"]=>
  string(6) "新晨"
  ["url"]=>
  string(1) "-"
  ["word"]=>
  string(1) "-"
  ["rpage"]=>
  string(30) "http://www.baidu.com/test.html"
  ["cpage"]=>
  string(1) "-"
  ["ip"]=>
  string(15) "117.151.180.150"
  ["ip_city"]=>
  string(31) "中国北京市 北京市移动"
  ["miao"]=>
  string(1) "5"
}
Copy after login

The above is the detailed content of What to do if php deserialization fails. For more information, please follow other related articles on the PHP Chinese website!

Related labels:
source:php.cn
Statement of this Website
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn
Popular Tutorials
More>
Latest Downloads
More>
Web Effects
Website Source Code
Website Materials
Front End Template