声明:本人只是在学习反序列化 因此这篇文章大量参考了https://blog.csdn.net/Hardworking666/article/details/122373938 这位的博客 感谢他的详细文章让我可以详细学习反序列化 大家想看更详细的可以直接参考他的文章!!!
序列化就是将数据格式
转化成可以存储和传输
的格式,原因是php文件正常执行结束会将文件销毁,那么下一次使用的时候就没有了,因此需要长久保存,就是序列化,也就是是使用serialize()
函数.
反序列化就是将可以传输的这种格式恢复成原本的对象,使用unserialize()
函数
+++
jsp
+++
基本单位
,也是现实中的一个具体事物,例如狗狗是一个对象蓝图
:定义了狗的特性(毛色 行为) 也可以由类产生具体对象不同表现
class Test//定义了一个类
public $variable = 'this is a variable' //定义了一个变量
pubilc function PrivateVariable() //定义了一个方法
$object = new Test(); //创建了一个对象
$object -> PrintVariable(); //创建了一个方法
?>
+++
都可以访问
到其自身或者父类 子类
访问被其定义的类所
访问注意: (\x00
代表空字符 必须占一个位置)
public:属性被序列化后属性值会变为属性名
privated:属性值被序列化后属性值会变成\x00*\x00属性名
privated:属性值被序列化后属性值会变成\x00类名\x00属性名
+++
两个下划线_
开头
__construct() //类的构造函数,创建对象时触发,用于初始化对象的属性或者执行一些启动工作
__destruct() //类的析构函数,对象被销毁时触发。用来释放资源或执行清理工作
__call() //当你调用一个对象的不可访问方法时触发。比如调用一个不存在的对象方法。
__callStatic() //当你调用一个静态方法时,但方法不存在时触发。
__get() //当你访问一个不可访问的属性时触发。比如访问私有属性。
__set() //当你给一个不可访问的属性赋值时触发。
__isset() //当你调用 isset() 或 empty() 判断不可访问属性时触发。
__unset() //当你用 unset() 删除不可访问属性时触发。
__invoke() //当你试图以函数的方式调用对象时触发
__sleep() //当你将对象序列化时触发,通常用于决定哪些属性应该被序列化。
__wakeup() //当你反序列化对象时触发,用于重新初始化某些状态。
__toString() //当你将对象作为字符串输出时触发。
从序列化到反序列化
_construct ->__sleep ->__wakeup() -> __toString ()-> __destruct()
class TestClass
{
//一个变量
public $variable = 'This is a string';
//一个方法 这个方法用于打印变量$variable 的值
public function PrintVariable()
{
echo $this->variable.'
';
}
//构造函数在创建函数时自动调用
public function __construct()
{ //简单输出__construct
echo '__construct
';
}
//析构函数在对象被摧毁时自动调用
public function __destruct()
{ //简单输出__destruct
echo '__destruct
';
}
//当对象被当作一个字符串,函数调用
public function __toString()
{
return '__toString
';
}
}
//创建一个对象
//__construct会被调用
$object = new TestClass();
//调用一个方法
//‘This is a string’将会被输出
$object->PrintVariable();
//对象被当作一个字符串
//toString会被调用
echo $object;
//php脚本要结束时,__destruct会被调用
?>
漏洞
:
+++
class User
{
//类的数据
public $age = 0; //初始值为0
public $name = ''; //初始值为空字符
//输出数据的方法
public function printdata()
{
//输出用户的年龄和姓名
echo 'User '.$this->name.' is '.$this->age.' years old.
';
} // “.”表示字符串连接
}
//创建User类的对象
$usr = new User();
//设置数据
$usr->age = 18;
$usr->name = 'Hardworking666';
//调用方法输出数据
$usr->printdata();
//输出序列化后的数据
echo serialize($usr)
?>
输出结果:
User Hardworking666 is 18 years old.
O:4:"User":2:{s:3:"age";i:18;s:4:"name";s:14:"Hardworking666";}
这里的输出结果第二行就是序列化
后的形式:
"o"表示对象,"4"表示对象名长度为4,"User"为对象名,“2”表示有2个参数
“{}”里面是参数的key和value
"s"表示string对象,"3"表示长度,“age”为key,"i"是interger(整数)对象,“18”是value
s:3:"age"
表示属性名是 age
,长度为 3 个字符。i:18
表示 age
属性的值是一个整数 18
。s:4:"name"
表示属性名是 name
,长度为 4 个字符。s:14:"Hardworking666"
表示 name
属性的值是一个字符串,长度为 14 个字符,内容是 "Hardworking666"
。
class User
{
//类的数据
public $age = 0;
public $name = '';
//输出数据
public function printdata()
{
echo 'User '.$this->name.' is '.$this->age.' years old.
';
}
}
//重建对象
$usr = unserialize('O:4:"User":2:{s:3:"age";i:18;s:4:"name";s:14:"Hardworking666";}');
//输出数据
$usr->printdata();
?>
输出结果:
User Hardworking666 is 18 years old.
a - array 数组型
b - boolean 布尔型
d - double 浮点型
i - integer 整数型
o - common object 共同对象
r - objec reference 对象引用
s - non-escaped binary string 非转义的二进制字符串
S - escaped binary string 转义的二进制字符串
C - custom object 自定义对象
O - class 对象
N - null 空
R - pointer reference 指针引用
U - unicode string Unicode 编码的字符串
这里会演示PHP中关于序列化和反序列化的一些特别行为,特别是 使用了魔术方法__sleep
和__wakeup
来控制序列化和反序列化过程中的行为,并且定义了__construct
和__destruct
来演示对象创建和销毁时的行为
class test
{
public $variable = '变量反序列化后都要销毁'; // 公共变量
public $variable2 = 'OTHER';
// 打印变量的方法
public function printvariable()
{
echo $this->variable . '
';
}
// 构造方法,创建对象时调用
public function __construct()
{
echo '__construct' . '
';
}
// 析构方法,销毁对象时调用
public function __destruct()
{
echo '__destruct' . '
';
}
// 在对象反序列化时调用
public function __wakeup()
{
echo '__wakeup' . '
';
}
// 在对象序列化时调用
public function __sleep()
{
echo '__sleep' . '
';
return array('variable', 'variable2'); // 只序列化这些属性
}
}
// 创建一个对象,回调用 __construct 这里直接输出construct
$object = new test(); // 输出:__construct
// 序列化一个对象,会调用 __sleep
$serialized = serialize($object); // 输出:__sleep
// 输出序列化后的字符串
print 'Serialized:' . $serialized . '
'; // 输出 Serialized:O:4:"test":2:{s:8:"variable";s:24:"变量反序列化后都要销毁";s:8:"variable2";s:5:"OTHER";}
// 反序列化对象,会调用 __wakeup
$object2 = unserialize($serialized); // 输出:__wakeup
// 调用 printvariable,会输出数据
$object2->printvariable(); // 输出:变量反序列化后都要销毁
// 脚本结束,会调用 __destruct
?>
输出结果:
__construct
__sleep
Serialized:O:4:"test":2:{s:8:"variable";s:24:"变量反序列化后都要销毁";s:8:"variable2";s:5:"OTHER";}
__wakeup
变量反序列化后都要销毁
__destruct
+++
服务器端