php反序列化

php在session存储和读取时,都会有一个序列化和反序列化的过程,PHP内置了多种处理器用于存取$_SESSION数据,都会对数据序列化和反序列化,源码中有session_start的时候会读取session,从而进行反序列化.
php.ini 中默认 session.serialize_handler 为 php_serialize,而 index.php 中将其设置为 php ,这个差异就导致了 sesssion 反序列化问题。

php_binary: 存储方式是,键名的长度对应的ASCII字符+键名+经过serialize()函数序列化处理的值
php: 存储方式是,键名+竖线+经过serialize()函数序列处理的值
php_serialize(php>5.5.4): 存储方式是,经过serialize()函数序列化处理的值

php有三种处理器对$_SESSION数据进行序列化和反序列化。

1、反序列化之后的内容为一个对象;

2、反序列化生成的对象里的值,由反序列化里的值提供,与原有类预定义的值无关;

3、反序列化不触发类的成员方法;需要调用方法后才能触发;

常见魔术方法:

魔术方法触发前提:魔术方法所在类(或对象)被调用

函数 触发时机
__construct() 实例化对象时,首先会去自动执行的一个方法
__destruct() 在对象的所有引用被删除或者当对象被显示销毁时执行的魔术方法(实例化结束后以及反序列化时会触发)
__sleep() 序列化serialize()函数回显检查类中是否存在__sleep(),如果存在,该方法会先被调用,然后才执行序列化操作
__wakeup() unserialize()之前会检查是否存在一个__wakeup()方法,如果存在,则会先调用__wakeup()方法
__tostring() 表达方式错误导致魔术方法触发(把对象当成字符串调用)
__invoke() 格式表达错误导致没魔术方法触发(把对象当成函数调用)
__call() 调用的方法不存在时触发(返回值:调用的不存在的方法的名称和参数)
__callStatic() 静态调用或调用成员常量时使用的方法不存在时触发(返回值:调用的不存在的方法的名称和参数)
__get() 调用的成员属性是私有属性或不存在时触发(返回值:不存在的成员属性的名称)
函数 触发时机
__set() 给不存在的成员属性赋值时触发(返回值:不存在的成员属性的名称和赋的值)
__isset() 对不可访问属性(私有的、受保护的或不存在的属性)使用isset()或empty()时,__isset()会被调用 (返回值:不存在的成员属性的名称)
__unset() 对不可访问属性使用unset()时触发(返回值:不存在的成员属性名称)
__clone() 当使用clone关键字拷贝完成一个对象后,新对象会自动调用定义的魔术方法__clone()
__serialize()(此特性自 PHP 7.4.0 起可用。) serialize()函数会检查类中是否存在一个魔术方法 __serialize() 。如果存在,该方法将在任何序列化之前优先执行。它必须以一个代表对象序列化形式的 键/值 成对的关联数组形式来返回。注:如果类中同时定义了__serialize()和__sleep()两个魔术方法,则只有__seriallize()方法会被调用,__sleep()方法会被忽略
__unserialize()(此特性自 PHP 7.4.0 起可用。) unserialize()检查是否存在具有名为__unserialize() 的魔术方法。注:如果类中同时定义了 __unserialize() 和 __wakeup()两个魔术方法,则只有 __unserialize() 方法会生效,__wakeup()方法会被忽略。

转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。