DeepSeek public static interface ObjectInputFilter.FilterInfo
·
ObjectInputFilter.FilterInfo 是 Java 中的一个静态内部接口,属于 java.io 包的一部分。它是在 Java 9 中引入的,作为对象反序列化过滤机制的一部分,用于提高 Java 反序列化的安全性。
接口定义
public static interface ObjectInputFilter.FilterInfo {
// 获取正在反序列化的类
Class<?> serialClass();
// 获取数组长度(如果是数组对象)
long arrayLength();
// 获取当前对象的深度(嵌套层级)
long depth();
// 获取已经读取的字节数
long streamBytes();
// 获取当前正在被反序列化的对象的引用
ObjectInputFilter.FilterInfo serialClass(Class<?> clazz);
}
主要方法说明
| 方法 | 描述 |
|---|---|
serialClass() |
返回正在被反序列化的类,如果类还未确定则返回 null |
arrayLength() |
如果是数组对象,返回数组的长度;否则返回 -1 |
depth() |
返回当前对象在反序列化流中的嵌套深度(从 1 开始) |
streamBytes() |
返回已经读取的字节数 |
serialClass(Class<?>) |
设置当前正在被反序列化的类 |
使用场景
FilterInfo 接口主要用于自定义的 ObjectInputFilter 中,在反序列化过程中提供关于当前正在反序列化的对象的信息,以便过滤器决定是否允许反序列化继续。
示例代码
import java.io.*;
import java.util.ArrayList;
public class ObjectFilterExample {
public static void main(String[] args) {
// 创建对象输入流并设置过滤器
try (ObjectInputStream ois = new ObjectInputStream(
new FileInputStream("data.ser"))) {
// 设置自定义过滤器
ois.setObjectFilter(info -> {
// 获取正在反序列化的类
Class<?> clazz = info.serialClass();
// 如果是 null(基本类型或数组),允许
if (clazz == null) {
return ObjectInputFilter.Status.ALLOWED;
}
// 检查类名
String className = clazz.getName();
// 只允许特定的类被反序列化
if (className.startsWith("java.util.ArrayList") ||
className.startsWith("java.lang.String") ||
className.startsWith("com.example.")) {
return ObjectInputFilter.Status.ALLOWED;
}
// 检查数组长度
if (clazz.isArray() && info.arrayLength() > 1000) {
System.out.println("数组太长,拒绝反序列化");
return ObjectInputFilter.Status.REJECTED;
}
// 检查嵌套深度
if (info.depth() > 10) {
System.out.println("对象嵌套太深,拒绝反序列化");
return ObjectInputFilter.Status.REJECTED;
}
// 检查流大小
if (info.streamBytes() > 1024 * 1024) { // 超过 1MB
System.out.println("流太大,拒绝反序列化");
return ObjectInputFilter.Status.REJECTED;
}
// 默认拒绝
return ObjectInputFilter.Status.REJECTED;
});
// 读取对象
Object obj = ois.readObject();
System.out.println("反序列化成功: " + obj);
} catch (Exception e) {
e.printStackTrace();
}
}
}
// 使用 lambda 表达式的更简洁示例
class SimpleFilterExample {
public static void main(String[] args) {
// 创建一个简单的过滤器,只允许 ArrayList 和 String
ObjectInputFilter filter = info -> {
Class<?> clazz = info.serialClass();
if (clazz == null) {
return ObjectInputFilter.Status.ALLOWED;
}
if (clazz == ArrayList.class || clazz == String.class) {
return ObjectInputFilter.Status.ALLOWED;
}
return ObjectInputFilter.Status.REJECTED;
};
// 使用过滤器
try (ObjectInputStream ois = new ObjectInputStream(
new FileInputStream("data.ser"))) {
ois.setObjectFilter(filter);
Object obj = ois.readObject();
} catch (Exception e) {
e.printStackTrace();
}
}
}
过滤器状态返回值
过滤器方法需要返回一个 ObjectInputFilter.Status 枚举值:
| 状态 | 含义 |
|---|---|
ALLOWED |
允许反序列化 |
REJECTED |
拒绝反序列化 |
UNDECIDED |
未决定,让后续的过滤器决定 |
主要用途
- 安全防护:防止反序列化攻击,只允许信任的类被反序列化
- 资源控制:限制数组长度、对象深度、流大小,防止内存溢出
- 调试监控:记录反序列化的对象信息
- 兼容性控制:确保只有兼容的类版本被反序列化
注意事项
FilterInfo接口是在反序列化过程中动态提供信息的- 过滤器应该尽快做出决定,避免影响性能
- 可以链式组合多个过滤器
- 对于数组,
serialClass()返回数组类型,arrayLength()提供长度信息 - 过滤器可以在系统级别、流级别或对象级别设置
这个接口是 Java 反序列化安全机制的核心部分,通过它可以有效防范不安全的反序列化操作。
更多推荐



所有评论(0)