更新记录:Java9(JEP 290),Java17(JEP 415),Java(now)–2024.08.24
Java9
JEP 290: Filter Incoming Serialization Data
“核心机制是由序列化客户端实现并设置在ObjectInputStream.在反序列化过程中调用过滤器接口方法,以验证正在反序列化的类、正在创建的数组的大小以及描述流长度、流深度和解码流时的引用数量的指标。过滤器返回接受、拒绝或保留未决定状态的状态。”
以上是jeps中的描述
简单说,java9在ObjectInputStream中添加了调用过滤器检查类的方法,这个过滤器包括了全局过滤器和局部过滤器,有限调用全局过滤器。
public class ObjectInputStream ... { public final void setObjectInputFilter(ObjectInputFilter filter); public final ObjectInputFilter getObjectInputFilter(ObjectInputFilter filter); }
在java9中查看具体的内容
- 获取安全管理的配置
- 判断是否具有SERIAL_FILTER_PERMISSION的权限
- 判断过滤器是否为空
- 设置过滤器
具体查看getSerialFilter
查看filterCheck
注意到checkinput
注意到对于非基本类型
具体使用的时候可以通过定义filter实现
public MyFilter() { this.filters = Arrays.asList( clazz -> clazz == String.class ? Status.ACCEPTED : Status.UNDECIDED, clazz -> clazz == Integer.class ? Status.ACCEPTED : Status.UNDECIDED, clazz -> clazz.getName().startsWith("com.abc") ? Status.ACCEPTED : Status.REJECTED ); }
Java 17
JEP 415: Context-Specific Deserialization Filters:
简单说就是在java9的基础上,将过滤器变成可以动态调整的。
Java9中通过synchronized(serialFilterLock) 确保在同一时刻只有一个线程能够执行这个代码块。防止多个线程同时访问和修改serialFilter,从而导致线程安全问题。
查看Java17中setObjectInputFilter
if (totalObjectRefs > 0 && !Caches.SET_FILTER_AFTER_READ) { throw new IllegalStateException( "filter can not be set after an object has been read"); }
在这里确保了在对象已经开始反序列化后,不能再设置或更改过滤器。
这里删除了java9中的synchronized (serialFilterLock):
===当前java===
在当前java中查看具体的内容
具体操作:
- 获取安全管理的配置
- 判断是否具有SERIAL_FILTER_PERMISSION的权限
- 判断是否已经读取对象
- 判断是否已经设置过滤器
- 判断之前的过滤器和新的过滤是否为空
- 设置新的过滤器
结合apply(),返回一个包含了之前过滤器和新过滤器的ObjectInputFilter对象
查看ObjectInputStream#filterCheck方法
注意到checkInput方法
查看ObjectInputFilter#checkinput方法
根据对象的引用数量、深度、字节数和数组长度来做初步判断,并对数组和基本类型采取特定处理。
对于非基本类型采用以下代码
调用调用一系列的过滤器,获取第一个不是Status.UNDECIDED状态的值,如果没有则返回一个空的Optional
具体使用的时候可以通过定义filters进行使用
public MyFilter() { this.filters = Arrays.asList( clazz -> clazz == String.class ? Status.ACCEPTED : Status.UNDECIDED, clazz -> clazz == Integer.class ? Status.ACCEPTED : Status.UNDECIDED, clazz -> clazz.getName().startsWith("com.abc") ? Status.ACCEPTED : Status.REJECTED ); }
也可以设置全局过滤器进行反序列化的校验。
不足
缺少中间版本的内容:
- Java 10 & 11 :改进JEP 290 ;
- Java 12 :再次改进JEP 290;
- Java 16 :强制强封装。
参考文章
JDK9新特性-JEP 290:过滤传入的序列化数据 | JEPs
分析JEP 290机制的Java实现 – FreeBuf网络安全行业门户
JDK17新特性-JEP 415:上下文特定的反序列化过滤器 | JEPs
Java 17 更新(12):支持上下文的序列化过滤器,又一次给序列化打补丁-腾讯云开发者社区-腾讯云 (tencent.com)