首页
学习
活动
专区
工具
TVP
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往

建议|在中国不是程序猿,不建议你用序列化!

Hi!我是小小,今天是本周的第四篇,本篇将会着重讲解关于Java序列化的内容

Java序列化

java序列化和反序列化数据,是通过ObjectOutputStream和ObjectInputStream这两个类来实现的,

举个例子:

要序列化的对象data1

序列化操作类SerializeTest

执行后会发现 序列化成功,输出文件data1,同时反序列化成功,我们可以从data1文件中反序列化出data1类,能够获取其中的信息。

我们看看data1文件, notepad打开它长这样

再按十六进制打开看看,

是的,这就是序列化。

Java序列化缺陷

无法跨语言

Java序列化目前只支持Java语言实现的框架,其它语言大部分都没有使用Java的序列化框架,也没有实现Java序列化这套协议,因此,如果两个基于不同语言编写的应用程序之间通信,使用Java序列化,则无法实现两个应用服务之间传输对象的序列化和反序列化。

容易被攻击

Java官网安全编码指导方针里有说明,“对于不信任数据的反序列化,从本质上来说是危险的,应该避免“。可见Java序列化并不是安全的。

我们知道对象是通过在 ObjectInputStream 上调用 readObject() 方法进行反序列化的,这个方法其实是一个神奇的构造器,它可以将类路径上几乎所有实现了 Serializable 接口的对象都实例化。这也就意味着,在反序列化字节流的过程中,该方法可以执行任意类型的代码,这是非常危险的。

对于需要长时间进行反序列化的对象,不需要执行任何代码,也可以发起一次攻击。攻击者可以创建循环对象链,然后将序列化后的对象传输到程序中反序列化,这种情况会导致 hashCode 方法被调用次数呈次方爆发式增长, 从而引发栈溢出异常。例如下面这个案例就可以很好地说明。

实现攻击的原理:Apache Commons Collections允许链式的任意的类函数反射调用,攻击者通过实现了Java序列化协议的端口,把攻击代码上传到服务器上,再由Apache Commons Collections里的TransformedMap来执行。

序列化后的流太大

序列化后的二进制流大小能体现序列化的性能。序列化后的二进制数组越大,占用的存储空间就越多,存储硬件的成本就越高。如果我们是进行网络传输,则占用的带宽就更多,这时就会影响到系统的吞吐量。

Java 序列化中使用了 ObjectOutputStream 来实现对象转二进制编码,那么这种序列化机制实现的二进制编码完成的二进制数组大小,相比于 NIO 中的 ByteBuffer 实现的二进制编码完成的数组大小,有没有区别呢?

结果

性能太差

如果序列化的速度慢,就会影响网络通信的效率,从而增加系统的响应时间。

运行结果

总结

Java 默认的序列化是通过 Serializable 接口实现的,只要类实现了该接口,同时生成一个默认的版本号,就可以实现序列化

序列化存在存在安全漏洞、不跨语言以及性能差等缺陷,

FastJson、Protobuf、Kryo 是比较有特点的,而且性能以及安全方面都得到了业界的认可,我们可以结合自身业务来选择一种适合的序列化框架

关于作者

我是小小,双鱼座的程序猿,我们下期再见~bye~

END

「 往期文章 」

  • 发表于:
  • 原文链接https://kuaibao.qq.com/s/20201224A03USS00?refer=cp_1026
  • 腾讯「腾讯云开发者社区」是腾讯内容开放平台帐号(企鹅号)传播渠道之一,根据《腾讯内容开放平台服务协议》转载发布内容。
  • 如有侵权,请联系 cloudcommunity@tencent.com 删除。

扫码

添加站长 进交流群

领取专属 10元无门槛券

私享最新 技术干货

扫码加入开发者社群
领券