资讯动态

fastjson存在反序列化漏洞?全面剖析禁用原因及迁移Jackson实战

发布时间:2026/9/6 12:41:53 来源:尧图企业网站定制
在很长一段时间里fastjson 都是 Java 后端项目里非常常见的 JSON 处理库。早期选择它理由很直接API 简单、序列化速度快、阿里巴巴出品网上资料也多。直到后来在几次安全巡检和依赖升级中我陆续发现 fastjson 在反序列化场景下的风险比想象中要高最终决定在维护的项目里彻底禁用 fastjson并逐步迁移到 Jackson。这中间经历了依赖排除、代码替换、兼容性测试、性能回归等一系列过程踩了不少坑也沉淀了一些经验。本文就围绕“为什么禁用 fastjson”这个话题从漏洞背景、原理拆解、迁移实战和工程建议几个方面展开希望能给正在做技术选型或准备移除 fastjson 的同学一些参考。1. fastjson 是什么为什么会成为争议焦点1.1 fastjson 的基本定位fastjson 是阿里巴巴开源的一个 Java JSON 处理库提供了序列化和反序列化功能可以把 Java 对象转换成 JSON 字符串也可以把 JSON 字符串转换回 Java 对象。它最大的特点是 API 简单比如String json JSON.toJSONString(obj); User user JSON.parseObject(json, User.class);这两行代码就能完成常见场景下的对象与 JSON 互转非常直接。在早期 Spring Boot 生态还没有完全普及、Jackson 配置还稍显繁琐的时候fastjson 在很多企业项目里被大量使用。1.2 为什么 fastjson 会成为安全焦点fastjson 之所以频繁出现在安全公告里核心原因在于它支持一种“基于类名自动实例化”的反序列化机制。简单理解就是 JSON 字符串里可以携带类的全限定名fastjson 在解析时会根据这个类名创建对象再填充字段值。这个特性原本是为了满足多态和某些框架的序列化需求但如果传入的类名被攻击者控制就可能触发危险的反射调用链最终演变成远程代码执行RCE漏洞。自从 fastjson 爆出第一个严重反序列化漏洞开始后续多个版本都被发现存在绕过和新的利用链。我曾经统计过自己负责的老项目在升级 fastjson 的过程中前前后后经历了不下三次版本号跳跃每次都要重新验证原有的序列化规则是否兼容。更麻烦的是安全扫描工具对 fastjson 的版本号非常敏感即使只是一个 demo 工程引入了低版本 fastjson也会被标记为高风险。1.3 禁用 fastjson 不等于否定它的价值这里先说明一个观点禁用 fastjson 并不是因为它完全不能使用而是从维护成本和风险控制角度做出的选择。对于一个长期维护的项目来说依赖库的安全性、可控性和可持续性优先级很高。fastjson 的迭代节奏虽然很快但安全问题反复出现每次都要消耗团队精力去跟进、升级、验证这种隐形成本很容易被低估。相比之下Jackson 作为 Spring Boot 默认的 JSON 框架生态地位更稳定社区维护更成熟安全问题的响应也更规范。所以迁移到 Jackson 在当前环境下是更稳妥的路线。2. fastjson 反序列化漏洞的核心原理2.1 反序列化漏洞的根本原因要理解 fastjson 为什么容易出问题需要先搞清楚反序列化的本质。反序列化就是把一串字节流或字符串恢复成内存中的对象。如果这个过程允许外部输入指定“要创建哪个类”并且框架会自动调用某些方法那么攻击者就有可能通过构造特殊字符串让程序创建出原本不该创建的对象进而触发危险操作。fastjson 中有一个非常关键的类JSON它解析 JSON 时支持type字段。看下面这个例子String json {\type\:\com.example.core.Runtime\,\cmd\:\open /System/Applications/Calculator.app\}; Object obj JSON.parse(json); System.out.println(obj.getClass());这段代码只是演示思路实际利用链会比这复杂很多。关键在于type指定了类名fastjson 会尝试创建该类的实例并把 JSON 里的字段赋值给对象属性。如果这个类的某个 setter 方法或构造函数里存在危险逻辑攻击者就能通过构造字段触发这些逻辑。历史上的多个 fastjson 漏洞利用链基本都是在寻找可被攻击者控制的 setter 或 getter并利用 Java 反射机制组合出能执行命令的调用链。2.2 从 1.2.x 到 1.2.84 的绕过与修复从漏洞演变过程来看fastjson 的修复模式基本上是“发现问题 - 添加黑名单/白名单 - 被绕过 - 再修复”。早期版本使用的是黑名单机制也就是禁止反序列化已知的危险类。但黑名单很难覆盖所有可能的利用链所以攻击者不断寻找黑名单之外的新类或者通过组合已有类来绕过限制。后来 fastjson 引入了 safeMode在1.2.68之后用户可以配置开启。开启 safeMode 后type的白名单限制会非常严格普通开发者使用parseObject(String, Class)这类方法时基本不受影响但如果代码中使用了parseObject(String)或JSON.parse(String)这种不带目标类型的写法就需要特殊注意。到了1.2.84版本fastjson 进一步加严了限制不过安全公告仍然要求使用者及时升级到最新版本并建议开启 safeMode 或使用 AutoType 白名单。需要提醒的是即使你的 fastjson 版本已经升级到最新只要代码中存在JSON.parseObject(json)这种自动类型解析的写法风险依然存在。真正稳妥的方案不是追着某一个版本打补丁而是从代码层面减少危险 API 的使用。2.3 不只是 RCE还有 DoS 和类加载风险除了远程代码执行fastjson 还存在拒绝服务DoS风险。某些特制的 JSON 字符串会导致解析时出现深层嵌套或超大对象消耗大量 CPU 和内存拖垮系统。还有一些漏洞利用链会加载远程类这也是为什么很多安全策略会禁用 fastjson 的自动类型加载。从我个人经历来说真正促使我下定决心禁用 fastjson 的不是某一次具体漏洞爆发而是“漏洞报告的频率”本身。当一个库每隔几个月就要因为安全问题发布新版本并且需要使用者手动干预才能降低风险这个库在长期项目中的维护成本就已经过高了。3. 环境准备与迁移前现状分析在彻底禁用 fastjson 之前我先是梳理了项目中的所有使用情况。这一步很关键没有全局盘点就直接替换很容易漏掉隐藏的调用点。3.1 确认项目中的 fastjson 引入方式常见的情况有两种直接在pom.xml或build.gradle中声明了 fastjson 依赖。间接通过其他第三方库传递依赖。第一种情况比较容易排查直接搜索fastjson关键字即可。第二种情况比较隐蔽需要借助依赖分析工具查看完整依赖树。以 Maven 为例可以使用命令mvn dependency:tree -Dincludescom.alibaba:fastjson输出结果类似[INFO] - com.alibaba:fastjson:jar:1.2.83:compile [INFO] \- com.xxx:common-utils:jar:2.0.0:compile [INFO] \- com.alibaba:fastjson:jar:1.2.73:compile如果看到多个 fastjson 版本说明依赖冲突已经存在。此时需要找到一个明确的上层依赖并考虑用排除或统一版本的方式处理。3.2 代码扫描与使用点盘点我建议先全局搜索以下常见 APIJSON.toJSONStringJSON.parseObjectJSON.parseArrayJSON.parseTypeReferenceJSONObjectJSONArrayJSONFieldJSONTypeSerializeConfigParserConfigFeatureSerializerFeature把这些使用点列成清单并在表格里标注所在的模块、文件、行号、用途序列化、反序列化、字段别名、日期格式等。只有充分掌握全部使用点才能制定合理的替换策略。下面是我做迁移分析时使用的一个示例清单模块文件行号使用场景order-serviceOrderController.java45返回订单 JSONbase-commonJsonUtils.java12封装统一 JSON 工具类user-centerUserService.java89解析第三方返回的用户信息gatewayLogFilter.java100记录请求参数日志3.3 制定迁移方案在确认使用点之后我建议分三步走第一步在依赖层面排除 fastjson确保不会因为传递依赖而再次引入。第二步编写或改造统一的 JSON 工具类把业务代码对 fastjson 的调用收敛到一个门面类中。第三步分批替换各模块的代码每替换完一个模块就进行单测和联调避免一次性大规模改动。这个过程中版本环境主要取决于你项目使用的 Spring Boot 版本。Spring Boot 2.x 默认使用 Jackson 2.xSpring Boot 3.x 使用 Jackson 2.14 或更高版本。如果你的项目用的就是 Spring Boot那么迁移到 Jackson 几乎不需要额外引入依赖因为spring-boot-starter-web中已经包含了jackson-databind。4. Jackson 核心能力与 fastjson 替代方案4.1 Jackson 基础用法Jackson 的核心类是ObjectMapper它负责所有序列化和反序列化操作。最简单的用法import com.fasterxml.jackson.databind.ObjectMapper; ObjectMapper objectMapper new ObjectMapper(); // 序列化 String json objectMapper.writeValueAsString(user); // 反序列化 User user objectMapper.readValue(json, User.class);建议把ObjectMapper声明为 Spring Bean 或静态工具类的唯一实例不要每次调用都new ObjectMapper()因为它的初始化成本较高而且复用实例可以统一定制配置。4.2 常用配置对照在 fastjson 中我们经常使用SerializerFeature和Feature来控制序列化行为。Jackson 中对应的配置有的是通过ObjectMapper配置有的是通过注解实现。常见的对照关系如下功能fastjsonJackson字段为 null 时不输出SerializerFeature.WriteMapNullValue控制是否输出 nullJsonInclude.Include.NON_NULL日期格式JSONField(formatyyyy-MM-dd HH:mm:ss)JsonFormat(patternyyyy-MM-dd HH:mm:ss)字段名映射JSONField(nameuser_name)JsonProperty(user_name)忽略未知字段Feature.IgnoreNotMatchFAIL_ON_UNKNOWN_PROPERTIES设置为 false序列化字段顺序JSONField(ordinal1)JsonPropertyOrder或JsonProperty(index1)循环引用处理SerializerFeature.DisableCircularReferenceDetectObjectMapper默认通过WRITE_DATES_AS_TIMESTAMPS等配置循环引用需要自定义处理这里要特别说明一下“循环引用”。fastjson 默认开启了循环引用检测在序列化自引用对象时会输出{$ref:$}之类的引用标识。Jackson 默认情况下遇到循环引用会抛出异常这是两者很明显的区别。如果你在迁移时遇到循环引用问题不要直接给 Jackson 加上一个忽略字段的注解了事最好重新设计对象结构把父子关系理清楚或者在序列化 DTO 层避免双向引用。4.3 处理泛型反序列化fastjson 中我们常用TypeReference来反序列化泛型类型比如处理ListUserListUser userList JSON.parseObject(json, new TypeReferenceListUser() {});Jackson 也有类似的TypeReferenceListUser userList objectMapper.readValue(json, new TypeReferenceListUser() {});两者的用法几乎一致只是包名不同。fastjson 的是com.alibaba.fastjson.TypeReferenceJackson 的是com.fasterxml.jackson.core.type.TypeReference。4.4 处理多态与 type这是从 fastjson 迁移到 Jackson 时最需要留意的点。fastjson 的type字段允许在 JSON 字符串中指定类名Jackson 则使用class或通过配置实现多态。默认情况下Jackson 反序列化时不会关心 JSON 中的类名只会按你传入的目标类型来创建对象因此更安全。如果你确实需要多态序列化可以使用 Jackson 的JsonTypeInfo注解但要注意白名单校验。比如JsonTypeInfo(use JsonTypeInfo.Id.NAME, include JsonTypeInfo.As.PROPERTY, property type) JsonSubTypes({ JsonSubTypes.Type(value Cat.class, name cat), JsonSubTypes.Type(value Dog.class, name dog) }) public class Animal { // ... }这样序列化时会输出type字段反序列化时也只允许cat和dog这两个白名单类型比 fastjson 的自动类型解析要安全得多。5. 完整迁移实战将 fastjson 替换为 Jackson5.1 创建演示项目结构为了更清晰地展示迁移过程我创建一个简单的 Spring Boot 项目模拟原本使用 fastjson 的接口然后逐步替换成 Jackson。项目结构如下fastjson-migration-demo/ ├── pom.xml └── src/main/java/com/example/demo/ ├── DemoApplication.java ├── controller/UserController.java ├── entity/User.java └── util/JsonUtils.java5.2 Maven 依赖处理假设原来的pom.xml中存在 fastjson 依赖需要先排除它。如果是直接依赖直接删除即可如果是传递依赖可以通过exclusions排除。完整示例pom.xml如下?xml version1.0 encodingUTF-8? project xmlnshttp://maven.apache.org/POM/4.0.0 xmlns:xsihttp://www.w3.org/2001/XMLSchema-instance xsi:schemaLocationhttp://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd modelVersion4.0.0/modelVersion parent groupIdorg.springframework.boot/groupId artifactIdspring-boot-starter-parent/artifactId version2.7.18/version relativePath/ /parent groupIdcom.example/groupId artifactIdfastjson-migration-demo/artifactId version1.0.0/version properties java.version1.8/java.version /properties dependencies dependency groupIdorg.springframework.boot/groupId artifactIdspring-boot-starter-web/artifactId /dependency /dependencies build plugins plugin groupIdorg.springframework.boot/groupId artifactIdspring-boot-maven-plugin/artifactId /plugin /plugins /build /project这里需要注意spring-boot-starter-web内置了 Jackson所以不需要额外添加jackson-databind依赖。如果你的项目不是 Spring Boot则需要手动添加dependency groupIdcom.fasterxml.jackson.core/groupId artifactIdjackson-databind/artifactId version2.15.4/version /dependency5.3 实体类改造原实体类中使用的是 fastjson 的JSONField注解package com.example.demo.entity; import com.alibaba.fastjson.annotation.JSONField; import java.util.Date; public class User { private Long id; JSONField(name user_name) private String userName; JSONField(format yyyy-MM-dd HH:mm:ss) private Date createTime; public Long getId() { return id; } public void setId(Long id) { this.id id; } public String getUserName() { return userName; } public void setUserName(String userName) { this.userName userName; } public Date getCreateTime() { return createTime; } public void setCreateTime(Date createTime) { this.createTime createTime; } }迁移为 Jackson 注解package com.example.demo.entity; import com.fasterxml.jackson.annotation.JsonFormat; import com.fasterxml.jackson.annotation.JsonProperty; import java.util.Date; public class User { private Long id; JsonProperty(user_name) private String userName; JsonFormat(pattern yyyy-MM-dd HH:mm:ss, timezone GMT8) private Date createTime; public Long getId() { return id; } public void setId(Long id) { this.id id; } public String getUserName() { return userName; } public void setUserName(String userName) { this.userName userName; } public Date getCreateTime() { return createTime; } public void setCreateTime(Date createTime) { this.createTime createTime; } }这里JsonFormat要比 fastjson 的format多指定timezone否则如果服务器时区不是东八区序列化出来的日期时间可能会差 8 个小时。5.4 统一 JSON 工具类改造原来的工具类package com.example.demo.util; import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.TypeReference; import java.util.List; public class JsonUtils { private JsonUtils() { } public static String toJson(Object obj) { return JSON.toJSONString(obj); } public static T T parseObject(String json, ClassT clazz) { return JSON.parseObject(json, clazz); } public static T ListT parseArray(String json, ClassT clazz) { return JSON.parseArray(json, clazz); } public static T T parseObject(String json, TypeReferenceT typeReference) { return JSON.parseObject(json, typeReference); } }改造为 Jacksonpackage com.example.demo.util; import com.fasterxml.jackson.core.JsonProcessingException; import com.fasterxml.jackson.core.type.TypeReference; import com.fasterxml.jackson.databind.DeserializationFeature; import com.fasterxml.jackson.databind.ObjectMapper; import java.util.List; public class JsonUtils { private static final ObjectMapper OBJECT_MAPPER new ObjectMapper(); static { // 反序列化时忽略未知字段 OBJECT_MAPPER.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false); // 序列化时忽略为 null 的字段 OBJECT_MAPPER.setSerializationInclusion(JsonInclude.Include.NON_NULL); } private JsonUtils() { } public static String toJson(Object obj) { try { return OBJECT_MAPPER.writeValueAsString(obj); } catch (JsonProcessingException e) { throw new RuntimeException(序列化失败, e); } } public static T T parseObject(String json, ClassT clazz) { try { return OBJECT_MAPPER.readValue(json, clazz); } catch (JsonProcessingException e) { throw new RuntimeException(反序列化失败, e); } } public static T ListT parseArray(String json, ClassT clazz) { try { return OBJECT_MAPPER.readValue(json, new TypeReferenceListT() {}); } catch (JsonProcessingException e) { throw new RuntimeException(反序列化List失败, e); } } public static T T parseObject(String json, TypeReferenceT typeReference) { try { return OBJECT_MAPPER.readValue(json, typeReference); } catch (JsonProcessingException e) { throw new RuntimeException(反序列化失败, e); } } }这里要注意“忽略未知字段”是一个很常见的配置因为在前后端对接时前端传入了新字段而后端实体还没更新如果不忽略未知字段反序列化会直接报错。但“忽略为 null 的字段”要根据实际场景决定如果接口层希望稳定返回所有的 key就不应该配置 NON_NULL。建议工具类不要把所有配置都写死而是让不同模块通过不同的ObjectMapper实例来处理。5.5 Controller 层改造原来的 Controllerpackage com.example.demo.controller; import com.alibaba.fastjson.JSON; import com.alibaba.fastjson.JSONObject; import com.example.demo.entity.User; import org.springframework.web.bind.annotation.*; RestController RequestMapping(/user) public class UserController { PostMapping(/create) public String createUser(RequestBody String body) { JSONObject jsonObject JSON.parseObject(body); String name jsonObject.getString(user_name); // 模拟业务逻辑 User user new User(); user.setId(1L); user.setUserName(name); return JSON.toJSONString(user); } }改造后package com.example.demo.controller; import com.example.demo.entity.User; import com.example.demo.util.JsonUtils; import org.springframework.web.bind.annotation.*; import java.util.Map; RestController RequestMapping(/user) public class UserController { PostMapping(/create) public String createUser(RequestBody String body) { MapString, Object map JsonUtils.parseObject(body, Map.class); String name (String) map.get(user_name); // 模拟业务逻辑 User user new User(); user.setId(1L); user.setUserName(name); return JsonUtils.toJson(user); } }这段代码的主要变化是不再使用 fastjson 的JSONObject而是使用Map来接收动态字段。如果你真的需要类似JSONObject的灵活容器Jackson 也有ObjectNode和JsonNode但日常业务中大可不必因为定义明确的 DTO 会让代码更清晰。5.6 运行与验证启动 Spring Boot 应用执行以下命令测试curl -X POST http://localhost:8080/user/create -H Content-Type: application/json -d {\user_name\:\张三\}预期返回{id:1,user_name:张三,createTime:null}如果配置了NON_NULL那么createTime为 null 时不会输出结果为{id:1,user_name:张三}同时我们可以在代码中加入以下测试验证JsonUtils的泛型解析String jsonArray [{\id\:1,\user_name\:\张三\},{\id\:2,\user_name\:\李四\}]; ListUser users JsonUtils.parseArray(jsonArray, User.class); System.out.println(users.size());输出为2。5.7 特殊场景处理在迁移过程中最常见的特殊场景有三个。第一个是Java 8时间类型LocalDateTime。Jackson 默认能处理LocalDateTime但输出格式比较难看需要在ObjectMapper上注册JavaTimeModule并配置格式。示例ObjectMapper objectMapper new ObjectMapper(); objectMapper.registerModule(new JavaTimeModule()); objectMapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);或者在字段上使用JsonFormatJsonFormat(pattern yyyy-MM-dd HH:mm:ss) private LocalDateTime createTime;第二个是枚举类型。fastjson 默认按枚举名称序列化和反序列化Jackson 默认也按名称处理但如果启用了WRITE_ENUMS_USING_TO_STRING行为会不一样。建议在实体类中为枚举添加JsonValue或JsonCreator来明确映射关系。第三个是BigDecimal精度。fastjson 在序列化BigDecimal时默认会输出科学计数法吗实际上有版本差异。Jackson 一般会输出普通数值但如果你在数据库查询结果中直接序列化某些复杂类型建议先转换成 DTO 再序列化。6. 常见问题与排错思路在禁用 fastjson 和迁移到 Jackson 的过程中下面这些问题非常典型整理成表格方便查阅。问题现象常见原因解决思路启动报错ClassNotFoundException: com.alibaba.fastjson.JSON还有代码引用 fastjson但依赖已被排除全局搜索import com.alibaba.fastjson并替换反序列化报错Unrecognized fieldJackson 默认拒绝未知字段配置FAIL_ON_UNKNOWN_PROPERTIESfalse或在类上使用JsonIgnoreProperties(ignoreUnknown true)日期格式变成时间戳未配置JavaTimeModule或未禁用时间戳输出注册JavaTimeModule并配置disable(WRITE_DATES_AS_TIMESTAMPS)字段名变成小写开头或与预期不一致实体属性命名不规范或者缺少JsonProperty检查 setter/getter 命名建议显式使用JsonProperty定义 JSON 字段名循环引用导致Infinite recursion实体存在双向关联如父子互相引用在 DTO 层拆分结构或使用JsonIgnore忽略某个方向泛型 List 解析后是LinkedHashMap反序列化时未使用TypeReference使用objectMapper.readValue(json, new TypeReferenceListUser() {})序列化LocalDateTime报错InvalidDefinitionException缺少jackson-datatype-jsr310依赖Spring Boot 项目需引入spring-boot-starter-json或手动添加jackson-datatype-jsr310如果项目中还残留很多 fastjson 调用可以使用 IDE 的全局替换功能先替换包的 import再逐个处理代码。但要注意很多方法是不能直接一对一替换的尤其是涉及JSONObject和JSONArray的地方设计上会有差异。7. 禁用 fastjson 后的最佳实践与工程建议7.1 建议建立 JSON 工具类门面不管使用什么 JSON 库我建议项目里都维护一个统一的JsonUtils工具类业务代码只依赖这个工具类不直接依赖 fastjson 或 Jackson 的 API。这样做的好处是如果未来想再次切换 JSON 库只需要修改工具类的内部实现业务代码完全不用动。我在迁移时因为之前的项目码已经大量直接调用JSON.toJSONString导致替换成本很高。如果从一开始就做好门面封装禁用 fastjson 会轻松很多。7.2 反序列化永远不要用无界的自动类型解析无论使用 fastjson、Jackson 还是 Gson都应该避免将外部输入的 JSON 直接解析成不确定类型。fastjson 的JSON.parseObject(String)不带目标类型就会出现自动类型猜测Jackson 虽然默认没有类似风险但如果滥用JsonNode或Map.class也可能引入类型混乱。正确的做法是定义明确的 DTO并在接口边界做参数校验。7.3 依赖检查应该纳入 CI在持续集成流水线中建议加入依赖检查和漏洞扫描。Maven 项目可以使用mvn dependency:tree检查依赖树也可以使用 OWASP Dependency-Check 或项目自身的依赖扫描插件。每次构建时如果检测到 fastjson 或已知漏洞版本应该让构建失败而不是只在代码评审时人工确认。7.4 生产环境变更前必须验证兼容性这里分享一个我走过的弯路。原本以为替换 JSON 库只是 API 层面的变化结果上线后出现了两个问题一个是日期格式从数组变成了字符串另一个是Map中 null 字段被序列化成了字符串null。这些都是 fastjson 与 Jackson 默认行为的差异。因此在迁移时一定要对比原接口的返回样例最好编写自动化测试来锁定 JSON 结构。涉及线上切换时建议先灰度发布一部分实例观察日志和调用方反馈再全量发布。7.5 不要频繁切换技术栈禁用 fastjson 是为了降低风险但并意味着每出一个新 JSON 库就要追新。Jackson 当前已经是事实标准如果项目没有特殊需求没必要再引入其他 JSON 框架。另外如果你的团队对 Jackson 不熟悉建议先在公共模块中封装好常用功能并补充使用文档减少同事的学习成本。8. 总结与后续学习建议从之前犹豫要不要升级 fastjson 版本到最终决定禁用并迁移到 Jackson整个过程让我更深刻地理解了反序列化安全的重要性。fastjson 的 API 确实简单历史贡献也值得肯定但在安全维护成本、社区生态和可控性几个维度上Jackson 目前更适合大多数项目。我在这次迁移中最大的收获不是替换了某几个 API而是养成了依赖排查和风险前瞻的习惯。如果你也要在项目中禁用 fastjson建议先做依赖和代码使用点的盘点然后封装统一工具类逐模块替换最后通过自动化测试和灰度发布来验证兼容性。对于使用 fastjson 的存量代码不要指望一次性全部改完优先处理对外接口和核心链路再逐步清理边缘模块。这样才能在保证业务稳定的前提下彻底摆脱 fastjson 带来的安全隐患。

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价