PHP参数序列化解码核心是unserialize()函数,仅适用于PHP原生serialize()生成的字符串(如a:2:{...}、O:8:"stdClass":...),需验证格式、来源与安全性,禁用危险类并优先使用JSON处理外部输入。

PHP参数序列化解码,核心是使用 unserialize() 函数还原被 serialize() 处理过的字符串。但要注意:不是所有“看起来像序列化”的字符串都能直接用 unserialize() 安全解码,必须确认来源、格式和安全性。
确认是否为 PHP 原生序列化格式
PHP 的 `serialize()` 生成的字符串有固定结构,例如: - 数组:`a:2:{s:4:"name";s:4:"Jack";i:0;i:100;}` - 对象:`O:8:"stdClass":2:{s:4:"name";s:4:"Jack";s:3:"age";i:25;}` - 字符串、整数等也带类型前缀(`s:`、`i:`、`a:`、`O:` 等)如果参数是这类格式,才适用 unserialize()。
常见误判:把 JSON 字符串(如 {"name":"Jack"})当成 PHP 序列化数据去 unserialize(),会直接失败并报错或返回 false。
判断方法:
- 用正则粗略匹配:
/^([aisO]):/—— 开头是 a/i/s/O 字符之一 - 用
unserialize($str, ['allowed_classes' => false])(PHP 7.4+)做试探性解析,避免自动实例化类
基础解码操作:unserialize() 的正确用法
```php $serialized = 'a:2:{s:4:"name";s:4:"Jack";s:3:"age";i:25;}'; $data = unserialize($serialized);if ($data === false && $serialized !== 'b:0;') { // 注意:unserialize() 失败时返回 false,但空布尔值 'b:0;' 是合法的 throw new Exception('反序列化失败:格式错误或含非法内容'); }
var_dump($data); // 输出:array(2) { ["name"]=> string(4) "Jack" ["age"]=> int(25) }
<p>关键细节:</p> <ul> <li>输入必须是完整、未截断的序列化字符串;缺一个字符就可能失败</li> <li>PHP 7.4+ 推荐显式传入选项:<code>['allowed_classes' => false]</code> 阻止对象实例化,提升安全性</li> <li>若原始数据含自定义类,需确保类已定义,或设置 <code>unserialize_callback_func</code> 处理未定义类</li> </ul> --- <H3>常见陷阱与安全提醒</H3> PHP 反序列化不是单纯的数据还原,它可能触发对象的魔术方法(如 `__wakeup()`、`__destruct()`),一旦参数来自不可信来源(如 GET、POST、Cookie、文件),就存在远程代码执行(RCE)风险。 <p>务必做到:</p> <ul> <li>只对内部可信数据使用 <code>unserialize()</code>;外部输入优先改用 <code>json_decode()</code></li> <li>禁用危险类:用 <code>allowed_classes => false</code> 或白名单数组(如 <code>['MySafeClass']</code>)</li> <li>不要在反序列化前手动修改字符串(如 base64_decode 后直接传给 unserialize),除非你100%确认原始编码方式</li> <li>session 数据虽经 serialize 处理,但应使用 <code>session_start()</code> + <code>$_SESSION</code> 访问,而非手动调用 <code>session_decode()</code> 解析原始字符串</li> </ul> --- <H3>其他“类序列化”参数的解码方式</H3> 有些场景下所谓“PHP参数序列化”实际是混合编码,需先还原再解析: <p>例如 Cookie 中的 session 数据:</p> <ul> <li>格式常为 <code>foo|s:3:"bar";name|s:4:"Jack";</code> —— 这是 PHP 的 <code>session.serialize_handler=php</code> 格式</li> <li>不能直接 <code>unserialize()</code> 整个字符串,而应先按 <code>;</code> 和 <code>|</code> 分割,再对每个值单独反序列化</li> <li>更稳妥做法:用 <code>session_decode($raw)</code>(仅限当前请求上下文),或改用 <code>php_serialize</code> handler 统一标准</li> </ul> <p>又如 Base64 编码的序列化字符串:</p> <ul> <li>先 <code>$raw = base64_decode($input)</code>,再 <code>unserialize($raw)</code></li> <li>注意:base64_decode 返回 <code>false</code> 表示解码失败(如长度不对、含非法字符)</li> </ul> 不复杂但容易忽略。



















