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()方法会被忽略。 |
转载请注明来源,欢迎对文章中的引用来源进行考证,欢迎指出任何有错误或不够清晰的表达。