序列化与反序列化介绍

文章目录

  • 一、序列化与反序列化简介
  • 二、序列化的目的
  • 三、什么时候需要序列化?
  • 四、序列化的注意事项
  • 五、序列化的方式
  • 六、反序列化漏洞
  • 参考链接


一、序列化与反序列化简介

序列化:把对象转化为可传输的字节序列过程称为序列化。
反序列化:把字节序列还原为对象的过程称为反序列化。

序列化 (Serialization) 是将对象的状态信息转换为可以存储或传输的形式的过程。在序列化期间,对象将其当前状态写入到临时或持久性存储区。以后,可以通过从存储区中读取或反序列化对象的状态,重新创建该对象。


二、序列化的目的

  1. 以某种存储形式使自定义对象持久化。(对象随着程序的运行而被创建,然后在不可达时被回收,生命周期是短暂的。但是如果我们想长久地把对象的内容保存起来怎么办呢?把它转化为字节序列保存在存储介质上即可。那就需要序列化。)
  2. 将对象从一个地方传递到另一个地方(网络传输)。(所有可在网络上传输的对象都必须是可序列化的,比如RMI(remote method invoke,即远程方法调用),传入的参数或返回的对象都是可序列化的,否则会出错;所有需要保存到磁盘的java对象都必须是可序列化的。)
  3. 进程间传递对象。(Android是基于Linux系统,不同进程之间的 java 对象是无法传输,所以我们此处要对对象进行序列化,从而实现对象在应用程序进程和ActivityManagerService进程之间传输。)

如果光看定义我想你很难一下子理解序列化的意义,那么我们可以从另一个角度来推导出什么是序列化, 那么究竟序列化的目的是什么?

其实序列化最终的目的是为了对象可以跨平台存储,和进行网络传输。而我们进行跨平台存储和网络传输的方式就是IO,而我们的IO支持的数据格式就是字节数组。

因为我们单方面的只把对象转成字节数组还不行,因为没有规则的字节数组我们是没办法把对象的本来面目还原回来的,所以我们必须在把对象转成字节数组的时候就制定一种规则(序列化),那么我们从IO流里面读出数据的时候再以这种规则把对象还原回来(反序列化)。

例如:如果我们要把一栋房子从一个地方运输到另一个地方去,序列化就是我把房子拆成一个个的砖块放到车子里,然后留下一张房子原来结构的图纸,反序列化就是我们把房子运输到了目的地以后,根据图纸把一块块砖头还原成房子原来面目的过程。


三、什么时候需要序列化?

通过上面我想你已经知道了凡是需要进行“跨平台存储”和”网络传输”的数据,都需要进行序列化。

本质上 存储和网络传输 都需要经过 把一个对象状态保存成一种跨平台识别的字节格式,然后其他的平台才可以通过字节信息解析还原对象信息。


四、序列化的注意事项

序列化使其他代码可以查看或修改那些不序列化便无法访问的对象实例数据。因此,代码执行序列化需要特殊的权限:即指定了 SerializationFormatter 标志的 SecurityPermission。在默认策略下,通过 Internet 下载的代码或 Internet 代码不会授予该权限;只有本地计算机上的代码才被授予该权限。

通常,对象实例的所有字段都会被序列化,这意味着数据会被表示为实例的序列化数据。这样,能够解释该格式的代码有可能能够确定这些数据的值,而不依赖于该成员的可访问性。类似地,反序列化从序列化的表示形式中提取数据,并直接设置对象状态,这也与可访问性规则无关。

对于任何可能包含重要的安全性数据的对象,如果可能,应该使该对象不可序列化。如果它必须为可序列化的,请尝试生成特定字段来保存不可序列化的重要数据。如果无法实现这一点,则应注意该数据会被公开给任何拥有序列化权限的代码,并确保不让任何恶意代码获得该权限。


五、序列化的方式

序列化只是一种拆装组装对象的规则,那么这种规则肯定也可能有多种多样。

目前JAVA常用的序列化有Protostuff,JSON,XML,Serializable,Hessian,Kryo(不支持跨语言)。

  • protobuf:谷歌公司出的一款开源项目,转码性能高,支持多语言;
  • JSON:用途最广泛,序列化方式还衍生了阿里的fastjson,美团的MSON,谷歌的GSON等更加优秀的转码工具。优点:使用方便。缺点:数据冗长,转码性能一般。

六、反序列化漏洞

反序列化是一系列安全问题的根源:攻击者能够将恶意数据序列化存储到数据库或内存中,当应用进行反序列化时,应用会执行到恶意代码。

在谷歌内部,这个缺陷被称为“疯狂的小部件 (Mad Gadget)”,外界对它的叫法是 “Java 启示录 (Apocalypse)”。

所以有一系列的规范来最大化避免:

  1. 对序列化对象执行完整性检查或加密,以防止恶意对象创建或数据篡改;最常见的例子之一就是JWT:JWT由3部分组成:Header,Payload,Verify Signature,最后的签名部分其实就是对数据进行完整性校验的关键部分,用secret对数据部分进行哈希计算,随后检查计算出来的哈希值是否和请求中的JWT签名部分的哈希值相同。若两者一致则认为数据完整性没有被破坏,若两者有差异则说明数据被修改过。
  2. 在创建对象之前强制执行严格的类型约束
  3. 隔离反序列化的代码,使其在非常低的特权环境中运行。
  4. 记录反序列化的例外情况和失败信息,如:传入的类型不是预期的类型,或者反序列处理引发的例外情况。
  5. 限制或监视来自于容器或服务器传入和传出的反序列化网络连接
  6. 监视反序列化行为,当用户持续进行反序列化时,对用户进行警告。

参考链接

  1. 序列化
  2. 序列化理解起来很简单
  3. 什么是序列化?序列化有什么作用?

你可能感兴趣的:(C语言与编程基础,开发语言)