Fastjson 开发随笔
常见使用问题
safeMode 导致反序列化失败
问题描述
Bean 对象序列化后的字符串包含 @type
字段:
1 | { "@type": "com.clay.system.model.User", "name": "peter" } |
使用 Fastjson 将字符串反序列化为 Bean 对象(反序列化时没有指定 Class 类型):
1 | User user = (User) JSON.parse(jsonString); |
Bean 对象会反序列化失败,并抛出以下异常:
1 | Could not deserialize: safeMode not support autoType : com.clay.system.model.User |
问题分析
Fastjson 在 1.2.68
及之后版本引入了 safeMode
安全机制,开启 safeMode
安全机制后会完全禁止 autoType
(自动类型识别),即使通过代码设置了白名单或者黑名单,autoType
也不会生效,从而会导致反序列化包含 @type
字段的 JSON 字符串时直接抛出异常,这样可以杜绝反序列化 Gadgets 类变种攻击。在部分项目中,首次反序列化操作可能触发 safemode
校验逻辑,而后续操作因缓存机制未再次触发异常。
版本区别
- Fastjson
2.x
默认启用了safeMode
安全机制,也就是默认禁用了autoType
自动类型识别。 - Fastjson
1.2.x
如果需要启用safeMode
安全机制,则需要手动调用ParserConfig.setSafeMode(true)
,而2.x
版本默认启用了safeMode
安全机制。
特别注意
- 如果 Fastjson 的版本号带有
_noneautotype
后缀(比如1.2.83_noneautotype
),则说明该版本是不支持autoType
的特殊构建版本,默认完全禁用了autoType
。 - Fastjson 的
_noneautotype
版本即使通过代码设置了白名单或者黑名单,autoType
也不会生效,详细说明请看这里。
问题解决
- (1) 使用
JSON.parseObject()
替代JSON.parse()
1 | // 正确写法,指定反序列化类型 |
1 | // 错误写法,依赖 @type 字段实现自动类型识别 |
- (2) 若 Fastjson 使用的是
1.2.83
及之后版本,可以配置全局关闭safeMode
,并配置白名单
1 | @Configuration |
- (3) 若 Fastjson 使用的是
noneautotype
版本,可以换成正常版本
1 | <!-- 正常版本 --> |
1 | <!-- noneautotype 版本 --> |
- (4) Fastjson
1.x
已经停止维护,若条件允许,推荐升级到 Fastjson2(2.0.x
版本)
1 | <dependency> |
然后使用 JSON.parseObject()
进行反序列化
1 | User user = JSON.parseObject(jsonString, User.class); |
参考资料
预览: