类型注册
本页介绍如何注册 Java 类,以及禁用类注册时如何限制允许使用的类。
类注册
类注册默认启用。它可以阻止输入选择未注册的应用类;按 ID 注册还能减小类元数据的体积。
反序列化不受信任的数据时,请保持类注册启用。如果需要禁用,请按下文所述配置 TypeChecker。
按 ID 注册
使用 Fory#register 时,可以让 Fory 自动分配 ID,也可以显式指定 ID:
Fory fory = Fory.builder().withXlang(false).build();
fory.register(Order.class); // 自动分配 ID
fory.register(Customer.class, 10); // 显式指定 ID
自动分配的 ID 取决于注册顺序,因此读取端和写入端必须按相同顺序注册相同的类。使用显式 ID 时,注册顺序可以不同,但两端的每个 ID 都必须映射到相同的类。
请在首次调用 serialize、deserialize 或 copy 之前完成类和序列化器注册。之后尝试注册会被拒绝。
启用类注册时,registerSerializer(Foo.class, ...) 足以让 Foo 可用。如果还希望 Fory 为其分配数字类型 ID,请使用 registerSerializerAndType(Foo.class, ...)。一组固定的常见 JDK 接口不需要显式注册,包括 Serializable、CharSequence、Comparable、Cloneable、Runnable、Callable、常见时间和集合接口、Comparator、Spliterator、Stream、Collector,以及 java.util.function 包中的类型。具体实现类仍遵循普通注册规则。
按名称注册
数字 ID 生成的类元数据最紧凑。如果协调数字 ID 不方便,可以按名称注册:
fory.register(Foo.class, "demo.Foo");
如果类型名称不会重复,可以使用不带命名空间前缀的名称,以减小序列化体积。
读取端和写入端必须为每个类注册相同的名称。按名称注册会比数字 ID 使用更多字节,但不依赖注册顺序。
安全配置
Type Checker
禁用类注册时,请使用 ForyBuilder#withTypeChecker 限制 Fory 可以序列化和反序列化的类。只有需要自定义匹配逻辑时才应实现 TypeChecker。数组类会以 Class#getName() 格式传给自定义检查器,例如 [[Lorg.example.Foo;。自定义检查器必须显式处理此格式;AllowListChecker 会自动处理数组组件名称。
AllowListChecker
AllowListChecker 支持按完整名称或包前缀配置允许和禁止规则:
AllowListChecker checker = new AllowListChecker(AllowListChecker.CheckLevel.STRICT);
checker.allowClass("org.example.*");
checker.disallowClass("org.example.internal.*");
Fory fory = Fory.builder().withXlang(false)
.requireClassRegistration(false)
.withTypeChecker(checker)
.build();
STRICT 会拒绝允许列表之外的所有类;WARN 会拒绝禁止的类,并对允许列表之外的类记录警告;DISABLE 会跳过允许列表检查。
请在首次调用 serialize、deserialize 或 copy 之前配置禁止规则。如需改用其他禁止规则,请创建新的 Fory 实例。
限制最大反序列化深度
ForyBuilder#withMaxDepth 用于限制嵌套反序列化深度,默认值为 50。当输入超过所配置的深度时,Fory 会抛出 ForyException。
Fory fory = Fory.builder()
.withXlang(false)
.withMaxDepth(100)
.build();
最佳实践
- 处理不受信任的输入时,保持类注册启用。
- 当读取端和写入端能够共享稳定的 ID 映射时,优先使用显式数字 ID。
- 自动分配 ID 时,确保两端使用相同的注册顺序。
- 在首次操作之前配置所有类、序列化器和禁止规则。
- 禁用类注册时配置
AllowListChecker。