Java Fastjson2 中的安全规则与快速 JSON 解析

如果你使用 Java 超过五年,Fastjson 这个名字可能会让你产生复杂的感受。一方面,这个库确实比 Jackson 更快。另一方面,通过 AutoType 的常规反序列化漏洞使其使用成为安全专家的噩梦。
Alibaba 团队比任何人都更清楚这些问题。两年前,他们从零开始重写了整个库。欢迎使用 Fastjson2:一个重新构想的 JSON 处理引擎,将安全性和现代 Java 版本的性能作为基础。
安全性的变化
第一个版本的主要问题是 AutoType 机制。它可以在解析过程中直接从 JSON payload 创建任意 Java 对象。攻击者经常找到绕过内置阻止类列表的方法并触发 RCE。
在 Fastjson2 中,方法发生了巨大变化。AutoType 现在默认禁用,类扫描不再依赖硬编码的白名单。引入了 SafeMode,完全禁止任意对象的自动组装。
所有配置标志现在都默认为 OFF。该库不再在可能导致危害的地方尝试猜测类型。
核心特性
开发者的目标是现代 JDK 版本,从 Java 8 到 Java 21。该引擎针对 Vector API、Record 类型和紧凑字符串进行了优化。
以下是使用该库时的亮点:
- 双格式支持。常规文本 JSON 和二进制 JSONB 协议。
- 通过 JSONPath 实现快速选择性解析,无需创建中间 Java 对象。
- Kotlin 扩展模块提供便捷的 DSL,全面支持 Spring Framework 5 和 6 版本。
- 开箱即用的 GraalVM Native Image 原生编译。
代码快速入门
添加库需要在 pom.xml 中包含单个依赖项:
解析和序列化的简单示例看起来很熟悉:
如果你用 Kotlin 编写,fastjson2-kotlin 模块提供简洁的扩展。代码由于 to<T>() 扩展函数而变得明显更清晰:
微服务的二进制 JSONB 格式
文本 JSON 仍然是 REST API 的标准,但在服务间通信中由于过大的体积和字符串转换开销而失去优势。Fastjson2 包含内置的二进制 JSONB 格式实现。
JSONB 将数据类型和结构编码为紧凑的字节集。这提供了显著的流量节省并加速了 RPC 服务。
使用 BeanToArray 选项进行压缩会将对象转换为值数组,避免重复字段名,使格式效率更接近 Protobuf 或 Kryo。
通过 JSONPath 选择性读取
通常,从微服务的大量 JSON 响应中,你只需要提取一个或两个字段。Jackson 等经典解析器首先在内存中构建完整的树或创建包含所有字段的对象,消耗 CPU 和内存资源。
Fastjson2 通过实现 SQL:2016 标准的 JSONPath 解决了这个问题。它可以直接从原始字节流中提取数据:
这个技巧在高性能数据处理管道中很有用,因为在 JVM 中不必要的对象分配会立即导致频繁的垃圾回收暂停。
从第一版迁移
在更改主版本时实现完全向后兼容性是不可能的,但作者试图简化过渡。为依赖旧 API 的项目创建了兼容性模块:
它使用旧的 groupId 和 com.alibaba.fastjson 包,但内部运行在新的 v2 引擎上。这使得在遗留代码中无需重写数百个导入就能进行更新。
但是,在迁移时需要注意重要的变化:
- 循环引用解析默认禁用。
- Smart Match 字段匹配不再开箱即用。
- 所有序列化器选项必须通过
JSONWriter.Feature明确启用。
Fastjson2 最终成为一个成熟可靠的产品。开发者从过去的错误中吸取了教训,消除了危险的默认设置,并为 Java 生态系统提供了一个真正快速的工具。
如果你正在开发高负载服务、使用 Spring 6 / GraalVM Native Image,或在 Kotlin 项目中寻找重型序列化格式的替代方案,Fastjson2 绝对值得一试。
相关项目