安全问题我们需要重视,立刻升级fastjson2

一、前言

小伙伴大家好,我是开源字节快速开发平台的作者。fastjson2.0 是fastjson的重要升级,目标是为下一个十年提供一个高性能的JSON库,同一套API支持JSON/JSONB两种协议。

近期fastjson 再报安全漏洞,直接给我们发送了高危告警,因此升级fastjson迫在眉睫。

FasterXML Jackson是美国FasterXML公司的一款适用于Java的数据处理工具。Jackson-databind是其中的一个具有数据绑定功能的组件。Jackson-databind可以将Java对象转换成json对象,同样也可以将json转换成Java对象。

暂且不说 fastjson2 的性能提升,在安全方面也值得我们去升级,这也是我们必须要去做的事。

二、罪魁祸首 AutoType

fastjson、jackson 都支持 AutoType 功能,这个功能在序列化的 JSON 字符串中带上类型信息,在反序列化时,不需要传入类型,实现自动类型识别。

三、fastjson1 安全问题

fastjson 1.x 内部维护了一个白名单,java 发展近 30 年难免有些漏网之鱼,这也造成近几年 fastjson 安全漏洞频发。

四、fastjson2 的设计

  • fastjson2 AutoType 必须显示打开才能使用,没有任何白名单,也不包括任何 Exception 类的白名单。这可以保证缺省配置下是安全的。

序列化时带上类型信息,需要使用 JSONWriter.Feature.WriteClassName。比如:

Bean bean = ...;
String jsonString = JSON.toJSONString
(bean, JSONWriter.Feature.WriteClassName);

很多时候,root对象是可以知道类型的,里面的对象字段是基类或者不确定类型,这个时候不输出root对象的类型信息,可以减少序列化结果的大小,也能提升反序列化的性能。

Bean bean = ...;
String jsonString = JSON.toJSONString
(bean, JSONWriter.Feature.WriteClassName, 
JSONWriter.Feature.NotWriteRootClassName);

反序列化打开AutoType功能支持自动类型

Bean bean = (Bean) JSON.parseObject
(jsonString, Object.class, JSONReader.Feature.SupportAutoType);
  • fastjson2 AutoType 支持配置 safeMode,在 safeMode 打开后,显式传入 AutoType 参数也不起作用,具体配置如下:
-Dfastjson2.parser.safeMode=true
  • fastjson2 AutoType 会经过内置黑名单过滤。该黑名单能拦截大部分常见风险,这个机制不能保证绝对安全,打开 AutoType 不应该在暴露在公网的场景下使用。

五、序列化示例代码

使用FastJson2JsonRedisSerializer实现RedisSerializer接口

public class FastJson2JsonRedisSerializer<T> 
implements RedisSerializer<T>
{
    public static final Charset DEFAULT_CHARSET
    = Charset.forName("UTF-8");
    private Class<T> clazz;
    public FastJson2JsonRedisSerializer(Class<T> clazz)
    {
        super();
        this.clazz = clazz;
    }
    @Override
    public byte[] serialize(T t) throws SerializationException
    {
        if (t == null)
        {
            return new byte[0];
        }
        return JSON.toJSONString
        (t, JSONWriter.Feature.WriteClassName).getBytes
        (DEFAULT_CHARSET);
    }
    @Override
    public T deserialize(byte[] bytes) throws SerializationException
    {
        if (bytes == null || bytes.length <= 0)
        {
            return null;
        }
        String str = new String(bytes, DEFAULT_CHARSET);
        return JSON.parseObject
        (str, clazz, JSONReader.Feature.SupportAutoType);
    }
}

六、升级到 fastjson2

6.1 兼容模式升级

升级可以通过兼容模式升级,兼容模式不需要改代码,但在深度使用的场景,不能做到完全兼容。

  • 兼容模式Maven依赖
<dependency>
    <groupId>com.alibaba</groupId>
    <artifactId>fastjson</artifactId>
    <version>${fastjson2.version}</version>
</dependency>

6.2 使用新API升级

使用新API是建议的升级方式,使用新的API能获得更多的功能。

  • 包名编程 FASTJSON v2和1.x版本使用不同的package,新的package名称是com.alibaba.fastjson2,新package和之前不同,可以实现1.x和2.x共存
import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONObject;
import com.alibaba.fastjson2.JSONArray;
  • Maven依赖 Maven依赖的groupId和1.x不同,使用了新的groupIdcom.alibaba.fastjson2
<dependency>
    <groupId>com.alibaba.fastjson2</groupId>
    <artifactId>fastjson2</artifactId>
    <version>${fastjson2.version}</version>
</dependency>

我们的项目没有强制依赖 fastjson1,所以选择了直接升级新 API。

最后

fastjson2 在性能和安全上都得到了很好的提升,开源字节开快速开发平台已经完成了升级,代码改动较大,fork了我们仓库的同学请及时更新,安全无小事,请慎重。

如若转载,请注明出处:开源字节   https://sourcebyte.vip/article/320.html

猜你喜欢

转载自blog.csdn.net/qq_35634154/article/details/131184716