什么是PHP序列化和反序列化
可以理解为拆分和组装。
序列化将数据对象转化为易存储、可传输的状态,结果为一串字符串;反序列化将序列化后的字符串重新还原为原来的数据对象。
举个栗子
<?php
class test{
public $a = 'satoru';
protected $b = '555';
private $c = false;
public function __displayVar()
{
echo $this->a;
}
}
$user=new test();
$e = serialize($user);
$d = unserialize($e);
var_dump($e);
var_dump($d);
?>
上面的代码中,看不懂的其他东西先不管,先看函数
serialize($user)
unserialize($user)
这两个函数就是序列化函数和反序列化函数,没啥解释的,一开始主要就是用这两个函数,下面看一下运行结果
//序列化结果
string(75) "O:4:"test":3:{s:1:"a";s:6:"satoru";s:4:" * b";s:3:"555";s:7:" test c";b:0;}"
//反序列化结果
object(test)#2 (3) {
["a"]=>
string(6) "satoru"
["b:protected"]=>
string(3) "555"
["c:private"]=>
bool(false)
}
基础知识(只是我个人学到的,可能不完整)
1、在上面的代码中,我们定义一个类后,其中的成员变量类型有三种:public、protected、private
public:公用的,在整个程序中都可使用;
protected:受保护的,只可在该类及该类的子类中使用;
private:私有的,只可在该类中使用。
2、初始化类
$user=new test();
3、序列化后字符串的组成
string(75) "O:4:"test":3:{s:1:"a";s:6:"satoru";s:4:" * b";s:3:"555";s:7:" test c";b:0;}"
这里在构造简单的payload时可能会用到(构造是只构造双引号里的,所以现在只看双引号里的,string[75]不用管)。
分析一下这串字符串由什么组成
- 对象O 类名名字符数4 变量名“test” 成员个数3
- 成员名的性质s:1:"a" 成员的内容s:6:"satoru"
- (s指string,1指字符a有一个字符,"a"指成员名)以此类推
构造的时候要按照这个格式构造,尤其要注意每个双引号不能漏。
使用时整体用单引号,可以注意看一下下面的代码。
4、反序列化生成的对象里的值,由反序列化里的的值提供,与原有定义类无关
还是举个栗子
<?php
class test{
public $a = 'satoru';
}
$d = new test();
$d = serialize($d);
$e = unserialize($d);
var_dump($e);
?>
这是定义类的原有数据,反序列化后输出的也是一样的值
object(test)#1 (1) {
["a"]=>
string(6) "satoru"
}
那如果改一下成员值呢,输出的是原有值还是改后的值?
注意改成员值时,也要把类型和字符数改成相应的。
<?php
class test{
public $a = 'satoru';
}
//$d = new test();
$d = 'O:4:"test":1:{s:1:"a";s:3:"123";}';
//$d = serialize($d);
$e = unserialize($d);
var_dump($e);
?>
我们将成员值改为"123",那么
object(test)#1 (1) {
["a"]=>
string(3) "123"
}
由此可见,类只是提供成员变量的背景而不决定成员变量的值,这点我们可以任意改变。
另外,类中定义的函数方法也是这样,类提供了函数的背景,只有类中的函数才能使用。(这里我的用语可能不是很规范,仅按照我的理解进行表达)