在php中的序列化与反序列化

序列化与反序列化的定义:

        序列化是指把对象转化为可传输的字节序列过程,而反序列化是指把字节序列还原为对象的过程。序列化和反序列化是数据持久化和网络传输中常用的技术手段,它们使得数据可以在不同平台、不同系统之间进行有效的存储和通信。

序列化详解:

  1. 概念解释:序列化是将对象的状态信息转换为可以存储或传输的形式(如字节流)的过程。这个过程可以通过不同的方式实现,例如使用Java内置的Serializable接口或者通过其他第三方库如JSON、XML等。

  2. 应用场景:序列化主要用于对象的持久化存储以及网络传输。在存储方面,它可以将对象保存到数据库或文件中;在网络传输方面,它允许对象通过网络发送到远程系统上,然后再反序列化成本地对象。

  3. 实现方法:在Java中,实现序列化的一种常见方法是让对象实现Serializable接口。这个接口虽然没有方法需要实现,但它标记了这个对象可以被JVM序列化和反序列化。

  4. 注意事项:在序列化过程中,静态字段和用transient关键字修饰的字段不会被序列化。此外,为了确保版本兼容性,建议显式定义serialVersionUID来控制版本的一致性。

  5. 性能考虑:选择序列化工具和技术时,需要考虑其性能和生成的数据大小。例如,Protobuf和MessagePack等工具提供了更小的消息大小和更快的序列化速度,适合在大规模分布式系统中使用。

反序列化详解:

  1. 概念解释:反序列化是将字节序列恢复成原有对象形态的过程。这一过程本质上是序列化的逆操作,要求能够准确地还原对象的状态。

  2. 应用场景:当数据从数据库或文件系统中读取出来,或者通过网络接收到序列化的数据后,客户端需要对这些数据进行反序列化,以重建原有的对象状态,进而执行业务逻辑处理。

  3. 实现方法:在Java中,使用ObjectInputStream类可以从输入流中读取字节序列,并将其反序列化为对象。这要求原始对象类实现了Serializable接口。

  4. 安全注意:反序列化过程可能存在安全风险,因为执行反序列化的过程中可能会运行恶意代码。因此,在处理不受信任的输入流时,应当格外小心,并采取相应的安全防护措施。

  5. 兼容性问题:如果序列化对象的类结构发生了变化(如添加了新的字段),可能导致反序列化失败。因此,管理serialVersionUID并合理设计类的结构变化对于保证反序列化的成功率至关重要。

总结而言,序列化与反序列化是数据处理和系统间通信不可或缺的技术。它们支持数据的持久化存储和跨网络传输,适用于多种场合,包括数据缓存、远程方法调用等。在选择具体的序列化技术时,应综合考虑性能、跨平台支持、安全性等因素,以适应不同的应用需求。

序列化与反序列化例子:
 

注意,当我们在序列化一个类的时候我们需要将该类定义出来。如下。

<?php
$raw = 'O:1:"A":1:{s:1:"a";s:1:"b";}';
var_dump(unserialize($raw));  //1进行反序列化并输出
echo serialize(unserialize($raw)); //2先进行反序列化再进行序列化。
?>

//输出结果1:
object(__PHP_Incomplete_Class)#1 (2) { ["__PHP_Incomplete_Class_Name"]=> string(1) "A" ["a"]=> string(1) "b" }

//输出结果2:
O:1:"A":1:{s:1:"a";s:1:"b";}

这段代码中的$raw字符串是一个序列化后的PHP对象。它包含了一个名为"A"的类的实例,该类有一个属性"a",其值为"b"。我们

$raw解析:

  1. O:1:"A":1:{s:1:"a";s:1:"b";}表示一个对象,其中:
    • O:1:"A"表示对象的类型为"A",并且该类型的类定义在当前命名空间中(即没有指定命名空间)。
    • 1表示对象的属性数量为1个。
    • {s:1:"a";s:1:"b";}表示对象的属性列表,其中:
      • s:1:"a"表示一个字符串类型的属性,属性名为"a",长度为1。
      • s:1:"b"表示另一个字符串类型的属性,属性名为"a"的值,长度为1。
  2. 反序列化$raw字符串后,会得到一个名为"A"的类的实例,该实例有一个属性"a",其值为"b"。

|我们通过对php的代码分析发现我们序列化了一个不存在的类“A“,但是当我们对$raw进行反序列化再序列化之后的输出和原来一样,这是为什么呢?
原因如下:

        可以发现PHP在遇到不存在的类时,会把不存在的类转换成__PHP_Incomplete_Class这种特殊的类,同时将原始的类名A存放在__PHP_Incomplete_Class_Name这个属性中,其余属性存放方式不变。而我们在序列化这个对象的时候,serialize遇到__PHP_Incomplete_Class这个特殊类会倒推回来,序列化成__PHP_Incomplete_Class_Name值为类名的类,我们看到的序列化结果不是O:22:"__PHP_Incomplete_Class_Name":2:{xxx}而是O:1:"A":1:{s:1:"a";s:1:"b";}

正常情况下的代码应该这样写:

<?php
class A {
    public $a;
}  //将A这个类定义出来

$raw = 'O:1:"A":1:{s:1:"a";s:1:"b";}';
$object = unserialize($raw);
var_dump($object);  //输出反序列化的结果
?>
//输出结果如下:
object(A)#1 (1) {
  ["a"]=>
  string(1) "b"
}

这表示我们成功地定义了类 "A",并通过反序列化得到了一个该类的实例,其中属性 $a 的值被正确设置为 "b"。

注意:

在实际应用中,序列化和反序列化数据时,确保在进行反序列化之前,相关的类已经被定义,以避免遇到__PHP_Incomplete_Class或其它潜在问题。

  • 5
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
PHP序列是将PHP对象转换为字符串的过程,以便在存储或传输时使用。序列后的字符串可以通过序列操作重新还原为原始的PHP对象。\[1\] 在PHP,可以使用serialize()函数将对象序列为字符串,然后使用unserialize()函数将字符串序列为对象。这样可以方便地在不同的环境传递和存储对象数据。 然而,序列操作也存在安全风险。恶意用户可以构造特定的序列字符串,以触发PHP序列漏洞,导致代码执行或敏感信息泄露。因此,在进行序列操作时,需要谨慎处理输入数据,验证和过滤不可信的序列字符串。 除了使用serialize()和unserialize()函数,还可以利用一些特殊的方式来触发PHP序列漏洞。例如,通过Phar序列,可以在不使用unserialize()函数的情况下触发PHP序列漏洞。当使用phar://伪协议读取phar文件时,会自动序列meta-data存储的信息,从而导致漏洞触发。\[2\]\[3\] 因此,在开发和使用PHP应用程序时,需要注意对序列序列操作进行安全处理,避免潜在的安全风险。这包括对输入数据进行验证和过滤,限制序列操作的权限,以及及时更新和修复可能存在的漏洞。 #### 引用[.reference_title] - *1* *2* *3* [PHP序列序列](https://blog.csdn.net/weixin_44033675/article/details/116809651)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^control,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值