最新下载
热门教程
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
php序列化serialize() 与反序列化unserialize()
时间:2022-06-24 17:24:06 编辑:袖梨 来源:一聚教程网
把复杂的数据类型压缩到一个字符串中
serialize() 把变量和它们的值编码成文本形式
unserialize() 恢复原先变量
eg:
代码如下 | 复制代码 |
$stooges = array('Moe','Larry','Curly'); 结果: |
当把这些序列化的数据放在URL中在页面之间会传递时,需要对这些数据调用urlencode(),以确保在其中的URL元字符进行处理:
代码如下 | 复制代码 |
$shopping = array('Poppy seed bagel' => 2,'Plain Bagel' =>1,'Lox' =>4); echo 'next'; |
margic_quotes_gpc和magic_quotes_runtime配置项的设置会影响传递到unserialize()中的数据。
如果magic_quotes_gpc项是启用的,那么在URL、POST变量以及cookies中传递的数据在反序列化之前必须用stripslashes()进行处理:
代码如下 | 复制代码 |
$new_cart = unserialize(stripslashes($cart)); //如果magic_quotes_gpc开启 |
如果magic_quotes_runtime是启用的,那么在向文件中写入序列化的数据之前必须用addslashes()进行处理,而在读取它们之前则必须用stripslashes()进行处理:
代码如下 | 复制代码 |
$fp = fopen('/tmp/cart','w'); fputs($fp,addslashes(serialize($a))); fclose($fp); //如果magic_quotes_runtime开启 //如果magic_quotes_runtime关闭 |
在启用了magic_quotes_runtime的情况下,从数据库中读取序列化的数据也必须经过stripslashes()的处理,保存到数据库中的序列化数据必须要经过addslashes()的处理,以便能够适当地存储。
代码如下 | 复制代码 |
mysql_query("insert into cart(id,data) values(1,'".addslashes(serialize($cart))."')"); $rs = mysql_query('select data from cart where id=1'); $ob = mysql_fetch_object($rs); //如果magic_quotes_runtime开启 //如果magic_quotes_runtime关闭 |
当对一个对象进行反序列化操作时,PHP会自动地调用其__wakeUp()方法。这样就使得对象能够重新建立起序列化时未能保留的各种状态。例如:数据库连接等。
用例子给你说明一下
代码如下 | 复制代码 |
//声明一个类 class dog { var $name; var $age; var $owner; function dog($in_name="unnamed",$in_age="0",$in_owner="unknown") { $this->name = $in_name; $this->age = $in_age; $this->owner = $in_owner; } function getage() { return ($this->age * 365); } function getowner() { return ($this->owner); } function getname() { return ($this->name); } } //实例化这个类 $ourfirstdog = new dog("Rover",12,"Lisa and Graham"); //用serialize函数将这个实例转化为一个序列化的字符串 $dogdisc = serialize($ourfirstdog); print $dogdisc; //$ourfirstdog 已经序列化为字符串 O:3:"dog":3:{s:4:"name";s:5:"Rover";s:3:"age";i:12;s:5:"owner";s:15:"Lisa and Graham";} /* ----------------------------------------------------------------------------------------- 在这里你可以将字符串 $dogdisc 存储到任何地方如 session,cookie,数据库,php文件 ----------------------------------------------------------------------------------------- */ //我们在此注销这个类 unset($ourfirstdog); ?> b.php
?>
//声明一个类 class dog { var $name; var $age; var $owner; function dog($in_name="unnamed",$in_age="0",$in_owner="unknown") { $this->name = $in_name; $this->age = $in_age; $this->owner = $in_owner; } function getage() { return ($this->age * 365); } function getowner() { return ($this->owner); } function getname() { return ($this->name); } } /*还原操作 */ /* ----------------------------------------------------------------------------------------- 在这里将字符串 $dogdisc 从你存储的地方读出来如 session,cookie,数据库,php文件 ----------------------------------------------------------------------------------------- */ $dogdisc='O:3:"dog":3:{s:4:"name";s:5:"Rover";s:3:"age";i:12;s:5:"owner";s:15:"Lisa and Graham";}'; //我们在这里用 unserialize() 还原已经序列化的对象 $pet = unserialize($dogdisc); //此时的 $pet 已经是前面的 $ourfirstdog 对象了 //获得年龄和名字属性 $old = $pet->getage(); $name = $pet->getname(); //这个类此时无需实例化可以继续使用,而且属性和值都是保持在序列化之前的状态 print "Our first dog is called $name and is $old days old ?> |
序列化与反序列化语法解析不一致带来的安全隐患
. PHP string serialize() 相关源码分析
------------------------------------
代码如下 | 复制代码 |
static inline void php_var_serialize_string(smart_str *buf, char *str, int len) /* {{{ */
|
通过上面的代码片段可以看到 serialize() 对 string 序列化处理方式如下:
代码如下 | 复制代码 |
$str = 'ryatsyne'; var_dump(serialize($str)); // $str serialized string output // s:8:"ryatsyne"; |
ii. PHP string unserialize() 相关源码分析
---------------------------------------
unserialize() 函数对 string 的反序列化则分为两种,一种是对 `s:` 格式的序列化 string 进行处理:
代码如下 | 复制代码 |
switch (yych) {
|
另一种是对 S: 格式的序列 string 进行处理(此格式在 serialize() 函数序列化处理中并没有定义):
代码如下 | 复制代码 |
static char *unserialize_str(const unsigned char **p, size_t *len, size_t maxlen)
|
从上面的代码片段可以看到 unserialize() 对序列化后的 string 反序列化处理如下:
代码如下 | 复制代码 |
$str1 = 's:8:"ryatsyne";';
|
iii. 语法解析处理不一致导致的安全隐患
-----------------------------
从上述分析过程可以看到 PHP 在反序列化 string 时没有严格按照序列化格式 s:x:"x"; 进行处理,没有对 " 后面的是否存在 ; 进行判断,同时增加了对十六进制形式字符串的处理,这样前后处理的不一致让人很费解,同时由于 PHP 手册中对此没有详细的说明,大部分程序员对此处理过程并不了解,这可能导致其在编码过程中出现疏漏,甚至导致严重的安全问题。
回到文章开头提到的 IPB 漏洞上,利用这个 funny feature of PHP 可以很容易的 bypass safeUnserialize() 函数的过滤:)
代码如下 | 复制代码 |
* mixed safe_unserialize(string $serialized) return false; |
相关文章
- 王者荣耀侦探能力大测试攻略 王者荣耀侦探能力大测试怎么过 11-22
- 无期迷途主线前瞻兑换码是什么 11-22
- 原神欧洛伦怎么培养 11-22
- 炉石传说网易云音乐联动怎么玩 11-22
- 永劫无间手游确幸转盘怎么样 11-22
- 无期迷途主线前瞻兑换码是什么 无期迷途主线前瞻直播兑换码介绍 11-22