php序列化用于持久化变量状态以跨请求复用,如登录态、缓存;含对象、私有属性、引用等时必须用serialize()而非json_encode();unserialize()有rce风险,严禁反序列化用户输入,需白名单控制且注意php版本兼容性。

PHP序列化是用来跨时间/跨空间保存变量状态的
它不是为了“存起来好看”,而是解决一个具体问题:PHP脚本执行完就销毁所有变量,但你想让某个数组或对象下次还能用——比如用户登录态、缓存数据、队列任务参数。这时候就得把它变成字符串存到文件、数据库或Redis里。serialize()干的就是这事:把内存里的结构打成一串可存储、可传输的字节流。
什么时候必须用serialize()而不是json_encode()
当你的变量含以下内容时,json_encode()会直接失败或丢数据,只能选serialize():
- 对象(尤其带私有/受保护属性、或实现了
__sleep()的) - 资源类型(如
fopen()返回的句柄——不过这类通常不该序列化) - 包含闭包的数组(PHP 7.4+ 仍不支持序列化闭包,但
serialize()至少报错明确) - 需要保留类名、属性可见性、内部引用关系的场景(比如两个数组元素指向同一个对象)
反过来说,如果只是传API数据、前端交互、或存纯数组/标量,json_encode()更安全、可读、跨语言。
unserialize()的安全风险比你想象中高得多
它不只是“还原变量”,而是会触发对象的__wakeup()、甚至在反序列化过程中执行任意代码——只要类定义里有危险逻辑。2019年ThinkPHP RCE漏洞就是典型例子。
Perl 基础入门中文教程,chm格式,讲述PERL概述、简单变量、操作符、列表和数组变量、文件读写、模式匹配、控制结构、子程序、关联数组/哈希表、格式化输出、文件系统、引用、面向对象、包和模块等知识点。适合初学者阅读和了解Perl脚本语言。
立即学习“PHP免费学习笔记(深入)”;
- 永远别对用户输入(如cookie、GET参数)直接调用
unserialize() - PHP 7.4+ 可用
unserialize($data, ['allowed_classes' => false])禁用对象反序列化 - 若必须支持特定类,显式列出白名单:
['allowed_classes' => ['MyCacheItem', 'UserData']] - Redis或Memcached里存
serialize()结果时,确保连接不被中间人劫持——因为篡改后的序列化字符串可能触发漏洞
性能和兼容性:别在PHP版本升级后忽略序列化格式变化
PHP 7.4 对对象序列化做了细微调整(比如属性顺序、空数组表示),导致7.4序列化的字符串在7.3上unserialize()可能失败或行为异常。
- 生产环境严禁混用不同主版本PHP做序列化/反序列化(如7.2写入,8.1读取)
- 跨服务通信(如PHP写、Python读)坚决别用
serialize(),改用JSON或Protocol Buffers - 存数据库时,字段类型建议用
TEXT而非VARCHAR(255)——序列化后字符串长度不可控,尤其含中文或大数组时 -
igbinary扩展能提升性能并减小体积,但会牺牲可读性和调试便利性,只在明确压测瓶颈后引入
序列化本身很简单,难的是想清楚“谁写、谁读、隔多久、换不换环境”。很多线上故障不是函数不会用,是忘了序列化字符串本质是一段带执行语义的二进制快照。










