对象序列化浅析

本文深入探讨了Java对象序列化的概念,即如何将对象转换为可跨平台存储和网络传输的字节数组。对象序列化主要用于数据持久化和网络通信。当需要进行跨平台存储或网络传输时,就需要使用序列化。Java中实现对象序列化只需让类实现Serializable接口。然而,静态属性和Transient修饰的属性不会被序列化。理解这些基本原理和限制对于有效地使用序列化至关重要。

对象序列化浅析

1、什么是序列化

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

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

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

2、什么情况下需要序列化

凡是需要进行“跨平台存储”和”网络传输”的数据,都需要进行序列化。

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

3、如何序列化

JDK(不支持跨语言)、JSON、XML、Hessian、Kryo(不支持跨语言)、Thrift、Protostuff、FST(不支持跨语言)

Java对象序列化实现方式

只需要实现Serializable 接口即可

4、常见问题

问题一:static 属性不能被序列化

序列化保存的是对象的状态,静态变量属于类的状态,因此 序列化并不保存静态变量

问题二:Transient 属性不会被序列化

Transient 属性不会被序列化

在[代码审计]帆软channel反序列化漏洞hsql链浅析利用中提到,在Jackson原生反序列化利用链里,com.fasterxml.jackson.databind.ObjectMapper#writeValueAsString方法会调用传入对象的无参getter方法,可利用com.fasterxml.jackson.databind.node.POJONode类来触发writeValueAsString方法[^2]。 一般来说,对帆软反序列化利用链分析,首先要明确触发反序列化的关键点。像Java序列化触发点,请求体传入的字节 byte[] var0 需经过一系列包装,如 ByteArrayInputStream var1 = new ByteArrayInputStream(var0); 、 GZIPInputStream var2 = new GZIPInputStream(var1) 、 CustomObjectInputStream var3 = new CustomObjectInputStream(var2) ,最后通过 (Map)var3.readObject() 进行反序列化操作[^5]。 对于利用链分析,还需要了解相关类的序列化和反序列化过程。以Hashtable为例,其序列化时,writObject会把table.length和count写入字节序列,分别代表table数组的长度和hashtable中的元素个数,table是一个Entry数组,用于存储键值对,之后遍历tabla数组将每个元素写入字节序列中;反序列化则有对应的操作来触发相关调用,例如在某些情况下会触发e.key.equals(key)等操作,从而形成利用链中的一环[^4][^3]。 而ysoserial的反序列化利用链分析虽和帆软不一定直接相关,但能提供一些思路。ysoserial的序列化数据(payload)构造是为了满足某条函数调用的路径,反序列化利用链分析多是函数调用栈的复述,如果没有亲自调试过,很难看懂相关文章,也难以确定自己是否学到位了[^1]。 ```java // 示例代码,简单展示反序列化触发的包装过程 import java.io.ByteArrayInputStream; import java.io.IOException; import java.io.ObjectInputStream; import java.util.Map; import java.util.zip.GZIPInputStream; class CustomObjectInputStream extends ObjectInputStream { public CustomObjectInputStream(java.io.InputStream in) throws IOException { super(in); } } public class DeserializationExample { public static void main(String[] args) throws IOException, ClassNotFoundException { byte[] var0 = new byte[0]; // 模拟请求体传入的字节 ByteArrayInputStream var1 = new ByteArrayInputStream(var0); GZIPInputStream var2 = new GZIPInputStream(var1); CustomObjectInputStream var3 = new CustomObjectInputStream(var2); Map result = (Map) var3.readObject(); } } ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值