JDK 17中的 java序列化过滤器 – Inside

21-10-26 banq

序列化过滤器首次出现在JDK 9,在 JDK 17获得更新,序列化过滤器使 Java 应用程序可以更好地控制传入数据的反序列化方式。
Java 中的序列化长期以来一直是一个令人头疼的问题,与它的实现方式有关的几个问题有关。其中一些问题包括:
  • 打破封装
  • 行为研究受控“魔术师”域和方法:readObject,writeObject,readObjectNoData,readResolve,writeReplace,等。

序列化过滤可用于保护您的应用程序免受不安全反序列化攻击。
过滤可以通过一个模式进行配置,该模式可以基于以下条件进行过滤:
  • 对象图的最大深度
  • 对象图的最大引用数
  • 对象图的最大字节数
  • 最大数组大小
  • 根据类名、包名或模块名按类型允许或拒绝

阅读此处了解如何构建模式。
 

三种使用方式

  • 设置为安全属性

在文件:
$JAVA_HOME/conf/security/java.security
中添加:
jdk.serialFilterFactory=<pattern>
  • 设置为 JVM 参数

-Djdk.serialFilter=<pattern>
  • 在代码中定义过滤器

可以使用工厂方法通过采用模式来创建过滤器:
ObjectInputFilter.Config.createFilter(String);
也可实施自定义过滤器:
ObjectInputFilter与基于模式的过滤器相比,该接口还可以实现为过滤序列化数据提供更大的灵活性:

class Filter implements ObjectInputFilter {

    @Override
    public Status checkInput(FilterInfo filterInfo) {
        ...
        return null;
    }
    
}

代码中定义的过滤器可以在 JVM 级别设置,甚至可以在单个流级别设置。
要在 JVM 范围内设置一个 fitler,setSerialFilter如下例所示:
ObjectInputFilter.Config.setSerialFilter(ObjectInputFilter);
要在单个流级别设置过滤器,请在要过滤setObjectInputFilter的流实例上使用:
ObjectInputStream.setObjectInputFilter(ObjectInputFilter);