经过多方调研,最终还是决定禁用FastJson

简介: 经过多方调研,最终还是决定禁用FastJson

老项目中使用到多种json类库,没有统一管理。最近开启全新的项目,准备对json类库进行统一,这样不仅能够压缩jar包的大小,也能够避免某个类库的漏洞导致系统问题。


其实,就在前几个月因为FastJson的漏洞,已经全面升级过一次FastJson的版本。现在项目中有用FastJson,有用gson,也有用Jackson。虽然用的类库比较多,但使用的场景并不多,还在可控范围之内。


这篇文章重点讲讲对FastJson的一些调研,虽然最终决定强制在项目中禁用FastJson,但在放弃之前,还是要学习一下这个类库的。


FastJson简介

Fastjson是阿里巴巴的开源JSON解析库,基于Java语言,支持JSON格式的字符串与JavaBean之间的相互转换。它采用一种“假定有序快速匹配”的算法,把JSON Parse的性能提升到了极致。


由于接口简单易用,已经被广泛使用在缓存序列化,协议交互,Web输出等各种应用场景中。


FastJson的简单示例

先用一个简单的示例来演示一下FastJson的使用。先在项目中引入FastJson类库:


<dependency>

   <groupId>com.alibaba</groupId>

   <artifactId>fastjson</artifactId>

   <version>1.2.70</version>

</dependency>


关于版本至少要在1.2.70以上,为啥?之前版本的漏洞太多。


定义个JavaBean,我们拿User为例:


public class User {
    private String userName;
    private int age;
    private String address;
    // getter/setter
}

使用实例:

public static void main(String[] args) {
    String json = "{\"address\":\"Beijing\",\"age\":28,\"user_name\":\"Tom\"}";
    // 将json转换为JavaBean
    User user = JSONObject.parseObject(json, User.class);
    System.out.println(user);
    // 将JavaBean转换为json
    String result = JSONObject.toJSONString(user);
    System.out.println(result);
}

实例中先将json字符串通过parseObject转换成User对象,然后又将User对象通过toJSONString方法转换成json。用起来是不是非常方便?


同时在构造json时你是否发现json字符串中有“user_name”这样的格式,FastJson默认会将这种下划线格式的key,与JavaBean中驼峰格式的属性进行绑定。


执行程序,打印结果:


User(userName=Tom, age=28, address=Beijing)

{"address":"Beijing","age":28,"userName":"Tom"}

1

2

可以看出成功执行。


FastJson还有其他一些常用的API,比如:


public static final Object parse(String text); // 把JSON文本parse为JSONObject或者JSONArray 
public static final JSONObject parseObject(String text); // 把JSON文本parse成JSONObject    
public static final <T> T parseObject(String text, Class<T> clazz); // 把JSON文本parse为JavaBean 
public static final JSONArray parseArray(String text); // 把JSON文本parse成JSONArray 
public static final <T> List<T> parseArray(String text, Class<T> clazz); //把JSON文本parse成JavaBean集合 
public static final String toJSONString(Object object); // 将JavaBean序列化为JSON文本 
public static final String toJSONString(Object object, boolean prettyFormat); // 将JavaBean序列化为带格式的JSON文本 
public static final Object toJSON(Object javaObject); //将JavaBean转换为JSONObject或者JSONArray。

通过上述API还可以实现:json字符串与JSONArray之间的转换、json字符串与javaBean之间的转换、json字符串-数组类型与javaBean之间的转换、JavaList与JsonArray之间的转换等。


为什么决定放弃FastJson

通过上面的示例来看FastJson的API使用起来也是非常简单,而且它的特点,也就是卖点就是“快”。


虽然网上有各种测试,质疑FastJson的“快”,但排除测试者测试用例或环境的影响,整体来看疑FastJson并不比市面上的其他同类框架慢。


那么放弃使用的原因是什么呢?


流行度

首先,它并不像我们想象中那么大受欢迎。来看一下FastJson的Maven引用量数据统计(来源https://mvnrepository.com/):


image.png可以看出FastJson排行第四,仅次于第三位的JSON In Java。如果考虑到国内大多数用阿里镜像,那么FastJson的排位要更靠前一些,但与Jackson相比差距还是有的。


设计与代码质量

在国外没有更受推广的原因大概有两个:推广(外加英文文档)和代码质量。


外国友人不喜欢FastJson是因为感觉代码质量不高。知乎上有一篇相关的文章,虽然写2016年,但也可以参考一下(链接:https://www.zhihu.com/question/44199956)。


image.png对于上述原因,我个人倒是更看重高赞回答中的总结“用很多投机取巧的的做法去实现所谓的’快’,而失去了原本应该兼容的java特性,对json标准遵循也不严格”。


是的,正是因为这个类库来源于阿里的实践,很多最初的设计与标准有一定的差距。而且已经被大量应用,就很难在后期改动。外加还经常出现不兼容性升级。


开源Issues

在写这篇文章时,看了一下GitHub上项目的Issues,还有大量的需要修复的问题。而且版本还在频繁的更新,修复升级。


image.png还有1488个问题处于Open状态!看到此处,真的有些担心了。用的人多,提问题的人多,也可以从另外一个方面来说可能更安全,但如果还有这么多问题待解决,还是有些恐怖的。


漏洞修复历史

同时,前段时间FastJson多次被爆存在漏洞,而这些漏洞都与FastJson中的一个AutoType特性有关。


从2019年7月份发布的v1.2.59一直到2020年6月份发布的 v1.2.71 ,每个版本的升级中都有关于AutoType的升级。


1.2.59发布,增强AutoType打开时的安全性 fastjson
1.2.60发布,增加了AutoType黑名单,修复拒绝服务安全问题 fastjson
1.2.61发布,增加AutoType安全黑名单 fastjson
1.2.62发布,增加AutoType黑名单、增强日期反序列化和JSONPath fastjson
1.2.66发布,Bug修复安全加固,并且做安全加固,补充了AutoType黑名单 fastjson
1.2.67发布,Bug修复安全加固,补充了AutoType黑名单 fastjson
1.2.68发布,支持GEOJSON,补充了AutoType黑名单。(引入一个safeMode的配置,配置safeMode后,无论白名单和黑名单,都不支持autoType。) fastjson
1.2.69发布,修复新发现高危AutoType开关绕过安全漏洞,补充了AutoType黑名单 fastjson
1.2.70发布,提升兼容性,补充了AutoType黑名单

那么什么是AutoType?为什么又会导致漏洞呢?


对于JSON框架Java对象转换成字符串通常可以基于属性或setter/getter方法。FastJson和Jackson是通过遍历出该类中的所有getter方法进行的,Gson是通过反射遍历该类中的所有属性,并把其值序列化成json。。


当一个类中包含了一个接口(或抽象类),在使用FastJson进行序列化的时候,会将子类型抹去,只保留接口(抽象类)的类型,使得反序列化时无法拿到原始类型。


因此,FastJson引入了AutoType,在序列化时把原始类型记录下来。


有了autoType功能,FastJson在对JSON字符串进行反序列化时,会读取@type到内容,试图把JSON内容反序列化成对象,并且会调用它的setter方法。利用这个特性,就可以构造一个JSON字符串,并且使用@type指定一个自己想要使用的攻击类库。


小结

虽然FastJson有这么多问题,虽然决定不再使用FastJson,但同样如知乎网友说的那样“温少几乎凭一己之力撑起了一个被广泛使用JSON库,而其他库几乎都是靠一整个团队,就凭这一点,温少作为“初心不改的阿里初代开源人”,当之无愧。”对于FastJson的漏洞问题还是给予理解和包容。



目录
相关文章
|
数据采集 存储 API
网络爬虫与数据采集:使用Python自动化获取网页数据
【4月更文挑战第12天】本文介绍了Python网络爬虫的基础知识,包括网络爬虫概念(请求网页、解析、存储数据和处理异常)和Python常用的爬虫库requests(发送HTTP请求)与BeautifulSoup(解析HTML)。通过基本流程示例展示了如何导入库、发送请求、解析网页、提取数据、存储数据及处理异常。还提到了Python爬虫的实际应用,如获取新闻数据和商品信息。
1864 2
|
Java 持续交付 数据库
避免服务分层污水池反模式
【6月更文挑战第30天】本文介绍污水池反模式,分层架构在敏捷性、部署性和性能方面得分较低,但具有高测试性和易开发性。关键在于合理分层以降低耦合和提高解耦效果。
503 1
避免服务分层污水池反模式
|
SQL 缓存 安全
深入解析MyBatis-Plus LambdaQueryWrapper与QueryWrapper:高效数据查询的秘密
深入解析MyBatis-Plus LambdaQueryWrapper与QueryWrapper:高效数据查询的秘密
13061 2
|
存储 Prometheus 运维
【云故事探索】NO.8:揭秘餐饮行业龙头 SaaS 厂商神州商龙的全栈可观测实践
天津市神州商龙科技股份有限公司成立于1998年,专为餐饮行业提供数字化解决方案。公司服务10万余家知名餐饮企业,确保用餐体验的稳定性至关重要。在业务容器化和微服务化过程中,神州商龙面临技术架构多样性、高可用要求及成本控制等挑战。通过尝试自建Prometheus和SkyWalking监控方案,最终选择阿里云Prometheus和日志服务SLS,实现了统一可观测平台,提升了监控效率、缩短故障排查时间、增强系统稳定性和优化资源利用率。未来,神州商龙计划引入机器学习和AI技术,提升自动化运维水平,并进一步整合业务系统监控数据。
【云故事探索】NO.8:揭秘餐饮行业龙头 SaaS 厂商神州商龙的全栈可观测实践
|
Prometheus 监控 Cloud Native
Java一分钟之-Micrometer:应用指标库
【6月更文挑战第11天】Micrometer是Java应用的度量库,提供统一API与多监控系统集成,如Prometheus、InfluxDB。它有标准化接口、广泛后端支持、自动配置和多种度量类型。常见问题包括度量命名不规范、数据过载和忽略维度。解决办法包括遵循命名规范、选择重要指标和使用标签。了解API、设计度量策略和选好监控系统是关键。通过正确使用Micrometer,可建立高效监控体系,保障应用稳定性和性能。
299 1
|
数据采集 存储 算法
HANTS时间序列滤波算法的MATLAB实现
HANTS时间序列滤波算法的MATLAB实现
260 1
|
存储 消息中间件 缓存
使用 Docker Compose 部署单机版 Redis:简单高效的数据缓存与存储
家人们啦!今天我们来介绍如何使用 docker-compose 部署单机版 Redis,这是一个简单高效的数据缓存与存储解决方案,广泛应用于Web应用、移动应用以及各类数据处理场景。我们过后几篇文章了将会介绍cluster和sentinel集群的部署。通过本文的指导,你将能够快速上手并体验 Redis 在你的应用中所带来的便捷性与高性能。废话不多说,让我们开始吧!
9389 1
使用 Docker Compose 部署单机版 Redis:简单高效的数据缓存与存储
|
Java Linux 数据处理
牛逼!继阿里、华为之后,腾讯也发布最新开源JDK
Kona 是由腾讯专业 JVM 技术团队维护开发的,基于 OpenJDK 的,提供长期支持并按季度更新的JDK发行版本。Kona 目前作为默认 JDK 应用于腾讯云业务场景及其他Java应用场景。
|
JSON fastjson Java
为什么我们公司强制弃坑FastJson了?主推Jackson~
为什么我们公司强制弃坑FastJson了?主推Jackson~
1295 0
为什么我们公司强制弃坑FastJson了?主推Jackson~
|
前端开发
CSS | 我看谁还不用这个UI库
最近新开不少项目,又实在是不想自己去定义特别多的 css 公共样式了,毕竟人多不好维护。于是找到了这个 tailwindcss UI 库。主要是内置了很多常用的 css 样式,前期避免了大量时间去写 css,中间开发也不用专门去维护,方便的一批。
412 0