Java 序列化边界怎么收紧:白名单与替代格式
来源:17golang原创
时间:2026-10-08 20:01:27 278浏览 收藏
Java 序列化边界要收紧,核心不是给 ObjectInputStream 再包一层异常,而是先限制“能读哪些类”,再限制“对象图能长多大”,最后把跨服务和不可信输入迁移到显式数据格式。只要输入不是完全受控的内部存储,就不应把原生反序列化当成通用消息协议。
- ObjectInputFilter 同时可以约束类名、数组长度、引用数、深度和输入字节数。
- 白名单要覆盖业务 DTO 及其确实需要的
java.base类型,不能用过宽的业务包通配。 - 新接口优先使用带版本的 DTO 格式,迁移时保留可观测的旧格式读路径,并设置明确的下线条件。
本文依据 Java 官方序列化过滤文档和 ObjectInputStream API 说明边界;官方地址:https://docs.oracle.com/en/java/javase/25/core/java-serialization-filters.html。
先按输入来源划出三层边界
可信的本地快照、同一版本服务生成的内部缓存,可以暂时保留原生序列化,但读取入口仍应有资源上限。来自 HTTP、消息队列、文件上传、插件或跨团队服务的数据,应视为不可信;最稳妥的做法是拒绝原生反序列化,改用只承载业务字段的 DTO。不要把“加了过滤器”理解成“输入已经安全”,过滤器只是在对象恢复前增加一道允许/拒绝判断。

建议把每个反序列化入口登记成一条策略:来源、允许的根对象、允许的包、最大深度、最大引用数、最大数组长度和最大字节数。这样异常日志里的 InvalidClassException 或过滤器拒绝原因,才能对应到具体业务入口,而不是只看到一条笼统的“反序列化失败”。
用白名单和资源上限保护 ObjectInputStream
简单场景可以使用 JVM 范围的模式过滤器;入口差异明显时,优先在每个流上设置更窄的过滤器。下面的模式只允许业务 DTO 和基础模块类型,同时限制对象图资源。!* 是拒绝其余类的关键边界,实际项目应把允许列表改成自己的稳定包名。
import java.io.ObjectInputFilter;
import java.io.ObjectInputStream;
// 只给受控 DTO 和必要的基础类型开门,同时限制对象图规模。
ObjectInputFilter filter = ObjectInputFilter.Config.createFilter(
"maxdepth=12;maxrefs=2000;maxbytes=1048576;maxarray=10000;"
+ "com.example.order.dto.*;java.base/*;!*"
);
try (ObjectInputStream input = new ObjectInputStream(source)) {
// 必须在第一次 readObject 前绑定过滤器,避免读取后再补策略。
input.setObjectInputFilter(filter);
OrderSnapshot snapshot = (OrderSnapshot) input.readObject();
// 反序列化只恢复 DTO;业务校验仍在这里或更靠后的服务层完成。
return snapshot;
} catch (java.io.InvalidClassException ex) {
// 被拒绝的类或资源上限属于输入失败,记录入口标识后丢弃该流。
throw new IllegalArgumentException("serialized input rejected", ex);
}
类名白名单和资源上限是两件事:前者阻止不需要的类型进入对象图,后者限制深度、引用数量、数组长度与字节消耗。即使业务对象本身在白名单内,也可能因为嵌套集合过深或输入过大而被拒绝。setObjectInputFilter 必须在读取对象前调用,而且过滤器不是业务字段校验器,日期范围、租户归属和状态转换仍要在 DTO 校验层处理。
用显式格式替代类路径驱动的跨服务协议
原生序列化把类名、字段演进和加载器关系带进载荷,跨服务升级时很容易变成隐式耦合。面向人工排查或开放接口,可采用 JSON;面向稳定 schema 和高吞吐二进制载荷,可采用 Protocol Buffers;需要二进制但保留较灵活结构时,可评估 CBOR。无论选哪一种,都让 DTO、版本字段和未知字段策略成为协议的一部分。

迁移不要一次性删除旧格式。可以先让新生产者写入显式格式,消费者保留旧格式只读并统计命中;当旧流量降到可接受范围,再把旧格式入口隔离到一次性迁移工具,最后删除服务运行时的 ObjectInputStream。双写期间要保证字段默认值、枚举未知值、时间精度和空值语义一致,避免“格式换了但业务含义悄悄变了”。
上线前用清单验收安全与兼容
- 来源清单:每个读取入口是否标明可信来源、根对象和责任服务。
- 过滤清单:是否有明确白名单;深度、引用、数组和字节上限是否来自样本而不是拍脑袋。
- 异常清单:被拒绝的类、超限输入和格式损坏是否有脱敏日志、指标和限流策略。
- 迁移清单:新旧格式的回放样本、版本兼容、回滚开关和旧入口下线时间是否写入发布记录。
最容易忽略的是把 java.base/* 当成万能信任。它只代表基础模块中的类型允许参与恢复,不代表业务对象可信,也不替代 DTO 字段校验。上线后应持续观察拒绝率、输入大小分布和旧格式命中率,按入口调整策略,而不是为了减少告警把白名单扩大到整个业务包。
相关问题
只配置 jdk.serialFilter 就够了吗?
它可以提供 JVM 范围的基线,但多个业务入口的允许类型不同,仍应补充流级或上下文级策略;配置也必须在部署参数中可追踪。
过滤器拒绝后能否继续读取同一个流?
不要把失败流交回正常业务路径。官方 API 将读取异常视为流状态不确定,应关闭并丢弃,再按入口记录原因。
换成 JSON 就不需要校验了吗?
不是。显式格式降低了类路径耦合,但仍要做大小限制、字段校验、版本兼容、权限和业务语义校验。
参考资料:https://docs.oracle.com/en/java/javase/25/core/java-serialization-filters.html;https://docs.oracle.com/en/java/javase/25/docs/api/java.base/java/io/ObjectInputStream.html;https://openjdk.org/jeps/290。
-
文章 · java教程 | 4星期前 | Java · 异常处理 · 资源管理 · java try-with-resources AutoCloseable close suppressed exception501 收藏
-
501 收藏
-
501 收藏
-
501 收藏
-
501 收藏
-
文章 · java教程 | 3小时前 | Java · 异常处理 · AutoCloseable Java try-with-resources suppressed exception 关闭顺序 getSuppressed197 收藏
-
462 收藏
-
212 收藏
-
446 收藏
-
414 收藏
-
文章 · java教程 | 1天前 | Java · 性能优化 · Stream · Java教程 · Java Stream Spliterator 并行流 parallelStream Stream副作用405 收藏
-
270 收藏
-
文章 · java教程 | 1天前 | 数据校验 · api设计 · Java教程 · 参数校验 Java record API DTO Jakarta Validation 紧凑规范构造器 跨字段校验370 收藏
-
文章 · java教程 | 1天前 | 线程池 · 异常处理 · 并发编程 · Java教程 · CompletableFuture · 异步任务 completablefuture allOf Handle 结果汇总 CompletionException482 收藏
-
425 收藏
-
484 收藏
-
200 收藏
-
- 前端进阶之JavaScript设计模式
- 设计模式是开发人员在软件开发过程中面临一般问题时的解决方案,代表了最佳的实践。本课程的主打内容包括JS常见设计模式以及具体应用场景,打造一站式知识长龙服务,适合有JS基础的同学学习。
- 立即学习 543次学习
-
- GO语言核心编程课程
- 本课程采用真实案例,全面具体可落地,从理论到实践,一步一步将GO核心编程技术、编程思想、底层实现融会贯通,使学习者贴近时代脉搏,做IT互联网时代的弄潮儿。
- 立即学习 516次学习
-
- 简单聊聊mysql8与网络通信
- 如有问题加微信:Le-studyg;在课程中,我们将首先介绍MySQL8的新特性,包括性能优化、安全增强、新数据类型等,帮助学生快速熟悉MySQL8的最新功能。接着,我们将深入解析MySQL的网络通信机制,包括协议、连接管理、数据传输等,让
- 立即学习 500次学习
-
- JavaScript正则表达式基础与实战
- 在任何一门编程语言中,正则表达式,都是一项重要的知识,它提供了高效的字符串匹配与捕获机制,可以极大的简化程序设计。
- 立即学习 487次学习
-
- 从零制作响应式网站—Grid布局
- 本系列教程将展示从零制作一个假想的网络科技公司官网,分为导航,轮播,关于我们,成功案例,服务流程,团队介绍,数据部分,公司动态,底部信息等内容区块。网站整体采用CSSGrid布局,支持响应式,有流畅过渡和展现动画。
- 立即学习 485次学习