PHP 在线反序列化怎么用:3 个参数坑先看清再动手

编程狮(w3cschool.cn) 2026-10-17 07:05:19 浏览数 (23)
反馈

PHP 在线反序列化工具做的事很单纯:把你粘进去的一段序列化字符串还原成 PHP 的数组或对象,直接显示结构。它适合排查缓存、Session、配置项里存的是什么,不适合处理来路不明的输入。用之前先看清三个参数坑:长度标记与实际字节不符、类在当前环境不存在、字符串里含不可见字符被编辑器吃掉。

在线反序列化怎么用3 个参数坑先看清

很多人第一次用是在排查线上问题:缓存里存的值看起来不对,想确认到底存了什么。这时把序列化字符串还原出来是最快的核对方式,比在代码里反复打日志省事。

本文讲清序列化字符串的构成、在线工具的三个使用步骤、三个参数坑的现象与修复方式,以及一条不能碰的安全红线。今天这篇文章,编程狮就把这块讲透。

先看结论

反序列化是把 serialize() 生成的字符串还原回 PHP 值的过程。在线工具省去了你写临时脚本的麻烦,但三个坑会让还原失败:长度标记写的字节数与实际内容不符、字符串里引用了当前环境不存在的类、以及私有属性里的不可见字符在复制粘贴时被丢掉。

判断顺序是先看报错位置,再核对长度标记,最后检查特殊字符。按这个顺序查,绝大多数还原失败都能定位。

语法细节若不熟,可以先翻 PHP 教程 把数组与对象的序列化规则过一遍。

一、它到底是什么:序列化字符串的构成

先看懂格式,才看得懂报错。

1.1 一段最小示例

<?php
$data = ['name' => '编程狮', 'url' => 'https://www.w3cschool.cn/'];
$s = serialize($data);
echo $s, PHP_EOL;
var_dump(unserialize($s));

上面这段代码做的是:把一个含中文站名的数组序列化成字符串,打印出来,再反序列化回去并打印结构。序列化字符串由「类型标记、长度、值」三段组成,比如 s:9:"编程狮" 里的 9 就是这段中文在 UTF-8 下的字节数。

1.2 类型标记速查

标记 含义 示例
s 字符串 s:3:"abc"
i 整数 i:42
a 数组 a:1:{...}
O 对象 O:8:"StdClass":0:{}
b 布尔 b:1

看懂标记后,报错信息里的 offset(偏移位置)就能直接对应到出错的那一段。

二、在线工具怎么用:三步与预期结果

流程很短,但每一步都有可核对的预期结果。

2.1 拿到完整的序列化字符串

从缓存、Session 存储或日志里把字符串整段复制出来。这一步最容易出的问题是只复制了一部分——字符串被日志截断时,后面所有还原都会失败。

2.2 粘进工具并选择还原

把字符串粘贴进输入框,执行还原。预期结果(未执行,依据序列化格式定义)是显示出对应的数组或对象结构。

2.3 核对结构而不是只看值

还原成功后要核对键名、类型、嵌套层级是否与预期一致。只扫一眼值很容易漏掉类型变化,比如字符串 "1" 和数字 1 看起来一样,落到代码里行为完全不同。

💡 小提示:中文内容的字节数最容易算错。UTF-8 下一个汉字占 3 个字节,手工改序列化字符串里的长度标记几乎必然出错,不要在编辑器里手改。

在线反序列化工具的三步使用流程

三、三个参数坑:现象、原因、修复

这三个坑覆盖了绝大多数还原失败。

3.1 长度标记与实际字节不符

现象是报错提示某个 offset 处出错。原因是字符串被截断、被编辑器改过,或者中文字节数算错。修复方式是重新取一份完整原始字符串,不要在编辑器里手工修正长度。

<?php
$bad = 'a:1:{s:4:"name";s:2:"编程狮";}';
$r = unserialize($bad);
var_dump($r);

上面这段代码演示的就是典型的长度不符:标记写的是 2 个字节,实际内容是 9 个字节。预期结果(未执行,依据反序列化对格式校验的行为)是还原失败并返回 false,同时报出偏移位置。

3.2 类在当前环境不存在

现象是还原出来一个 __PHP_Incomplete_Class 对象,属性虽然还在,但已经不是原来的类。原因是这段字符串来自另一个项目,那个类在当前环境没定义。修复方式是先引入对应的类定义,或者只把数据当成数组处理。

3.3 不可见字符被吃掉

私有属性的序列化结果里含有不可见的分隔字符,复制粘贴时很容易被丢掉。现象是看起来一模一样的字符串,还原却失败。修复方式是不要经过聊天工具或富文本编辑器中转,直接从源里取原始字节。

反序列化失败的三个参数坑与修复

四、安全边界:什么输入绝对不能还原

这一节比用法更重要。

4.1 不要还原不可信的输入

反序列化不可信数据可能触发对象注入:字符串里声明的类被自动加载,某些魔术方法随之执行。防护方式是只对可信来源的数据做反序列化,来自请求参数、Cookie、上传文件的一律不还原。

4.2 需要跨系统传数据时换格式

跨系统交换数据用 JSON。它没有对象自动加载的机制,语义也更通用。

<?php
$json = json_encode(['name' => '编程狮'], JSON_UNESCAPED_UNICODE);
var_dump(json_decode($json, true));

上面这段代码做的是用 JSON 做同样的存取,中文参数保证不被转义成 Unicode 序列。跨系统场景下这是更安全也更通用的选择。

⚠️ 注意:排查线上问题时,也不要把生产环境的真实序列化字符串贴到外部在线服务上,里面可能含用户数据。本机写一行脚本还原更安全。

总结

PHP 在线反序列化工具适合快速核对缓存、Session、配置里存了什么,用法是复制完整字符串、还原、核对结构三步。三个参数坑是长度标记不符、类不存在、不可见字符丢失。安全上只还原可信来源的数据,跨系统传数据改用 JSON。

要点带走:

  • 中文按字节算长度,UTF-8 下一个汉字 3 字节,不要手改长度标记;
  • 还原出 __PHP_Incomplete_Class 说明类没定义,先补类定义;
  • 来自请求参数、Cookie、上传文件的序列化数据一律不还原。

下一步建议把排查用的还原逻辑写成项目内的一个小脚本,既避免把生产数据贴到外部服务,也能复用。语法记不住时,翻 PHP 速查手册 最快。

常见问题

Q:反序列化报 offset 错误是什么意思?

A:说明字符串在某个字节位置不符合格式,最常见是长度标记与实际内容字节数不符。重新取一份完整的原始字符串,不要手工修长度。

Q:为什么还原出来是 __PHP_Incomplete_Class?

A:字符串里声明的类在当前环境没有定义。先引入对应类定义,或者只把它当数据数组处理。

Q:中文内容为什么总出问题?

A:UTF-8 下一个汉字占 3 个字节,而长度标记写的是字节数不是字符数。手工改标记几乎必然算错。

Q:用户提交过来的序列化数据能还原吗?

A:不能。不可信输入做反序列化存在对象注入风险,应改用 JSON 等纯数据格式交换。

延伸学习

想把这块弄清楚,可以按这个顺序来:

  1. 读一篇相关笔记 序列化与反序列化,看跨语言的共性设计;
  2. 需要快速核对时,PHP 反序列化工具 可以直接用;
  3. 想动手练,PHP 配套课程 把基础语法补齐。

0 人点赞