解决fastjson从1.1.41升级到1.2.28后报错问题详解

 更新时间:2020年02月07日 16:07:30   作者:漫夭  
这篇文章主要介绍了解决fastjson从1.1.41升级到1.2.28后报错问题详解,需要的朋友可以参考下

最近因为fastjson安全漏洞,升级jar包时,踩了一些坑。

新版本FastJsonHttpMessageConverter初始化,默认设置MediaType为*/*

背景:

使用Spring RestTemplate,配置如下:

  <bean id="restTemplate" class="org.springframework.web.client.RestTemplate">
    <constructor-arg ref="ky.clientHttpRequestFactory"/>
    <property name="errorHandler">
      <bean class="org.springframework.web.client.DefaultResponseErrorHandler"/>
    </property>
    <property name="messageConverters">
      <list>
        <bean class="org.springframework.http.converter.FormHttpMessageConverter"/>
        <bean class="cn.com.autodx.common.jsonView.ViewAwareJsonMessageConverter">
        </bean>
        <bean class="org.springframework.http.converter.StringHttpMessageConverter">
          <property name="supportedMediaTypes">
            <list>
              <value>text/html;charset=UTF-8</value>
              <value>application/json</value>
              <value>text/javascript;charset=utf-8</value>
            </list>
          </property>
        </bean>
      </list>
    </property>
  </bean>

其中ViewAwareJsonMessageConverter继承自FastJsonHttpMessageConverter。

fastjson从1.1.41升级到1.2.28之后,请求报错:

json java.lang.IllegalArgumentException: 'Content-Type' cannot contain wildcard type '*'

原因是在1.1.41中,FastJsonHttpMessageConverter初始化时,设置了MediaType。

  public FastJsonHttpMessageConverter(){
    super(new MediaType("application", "json", UTF8), new MediaType("application", "*+json", UTF8));
  }

而在1.2.28中,设置的MediaType为‘/',即:

  public FastJsonHttpMessageConverter() {
    super(MediaType.ALL); // */*
  }

后续在org.springframework.http.converter.AbstractHttpMessageConverter.write过程中,又要判断Content-Type不能含有通配符,这应该是一种保护机制,并强制用户自己配置MediaType。代码如下:

  @Override
  public final void write(final T t, MediaType contentType, HttpOutputMessage outputMessage)
      throws IOException, HttpMessageNotWritableException {
    final HttpHeaders headers = outputMessage.getHeaders();
    if (headers.getContentType() == null) {
      MediaType contentTypeToUse = contentType;
      if (contentType == null || contentType.isWildcardType() || contentType.isWildcardSubtype()) {
        contentTypeToUse = getDefaultContentType(t);
      }
      if (contentTypeToUse != null) {
      //设置Content-Type,不允许含有通配符
        headers.setContentType(contentTypeToUse);
      }
    }
    ......
    if (outputMessage instanceof StreamingHttpOutputMessage) {
      ......
    }else {
    //自定义MessageConverter的write操作
      writeInternal(t, outputMessage);
      outputMessage.getBody().flush();
    }
  }
  public void setContentType(MediaType mediaType) {
    Assert.isTrue(!mediaType.isWildcardType(), "'Content-Type' cannot contain wildcard type '*'");
    Assert.isTrue(!mediaType.isWildcardSubtype(), "'Content-Type' cannot contain wildcard subtype '*'");
    set(CONTENT_TYPE, mediaType.toString());
  }

所以,需要为ViewAwareJsonMessageConverter设置supportedMediaTypes:

<bean class="cn.com.autodx.common.jsonView.ViewAwareJsonMessageConverter">
  <property name="supportedMediaTypes">
    <list>
      <value>application/json;charset=UTF-8</value>
      <value>application/*+json;charset=UTF-8</value>
    </list>
  </property>
</bean>

新版本序列化默认不再对字段进行排序

这个是一个签名算法的场景:客户端对参数进行序列化,然后md5加密成一个签名;服务端按照相同的算法解析一遍参数,对比签名值。这里加密依赖json序列化之后的字符串,也就依赖序列化时字段的排序。

这是fastjson做了一个性能优化,将排序需求抽象出一个SerializerFeature,供用户自己配置。如果需要排序场景,在序列化时添加参数SerializerFeature.MapSortField即可,即:

JSON.toJSONString(obj, SerializerFeature.MapSortField);

官方文档

1.2.3之后的版本,Map的序列化没有做排序再输出,原因是通过TreeMap排序很影响性能。

1.2.27版本中增加SerializerFeature.MapSortField实现同样的功能。

使用方法如下:

a) 传入SerializerFeature.MapSortField参数。 JSON.toJSONString(map, SerializerFeature.MapSortField);

b) 通过代码修改全局缺省配置。 JSON.DEFAULT_GENERATE_FEATURE |= SerializerFeature.MapSortField.getMask();

c) 通过JVM启动参数配置修改全局配置 -Dfastjson.serializerFeatures.MapSortField=true

d) 通过类路径下的fastjson.properties来配置 fastjson.serializerFeatures.MapSortField=true

新老版本序列化和反序列化不兼容,会出乱码。

更多关于fastjson的相关文章请点击下面的相关链接

相关文章

  • Java使用NIO优化IO实现文件上传下载功能

    Java使用NIO优化IO实现文件上传下载功能

    IO 是基于流来读取的,而NIO则是基于块读取,面向流 的 I/O 系统一次一个字节地处理数据,这篇文章主要介绍了Java使用NIO优化IO实现文件上传下载功能,需要的朋友可以参考下
    2022-07-07
  • Java Apache Shiro安全框架快速开发详解流程

    Java Apache Shiro安全框架快速开发详解流程

    Apache Shiro是一个强大且易用的Java安全框架,执行身份验证、授权、密码和会话管理。使用Shiro的易于理解的API,您可以快速、轻松地获得任何应用程序,从最小的移动应用程序到最大的网络和企业应用程序
    2021-10-10
  • 在Java编程中使用正则表达式

    在Java编程中使用正则表达式

    这篇文章主要介绍了在Java编程中使用正则表达式,注意使用matches()方法检测一下Java对正则表达式的支持情况,需要的朋友可以参考下
    2015-08-08
  • springboot整合flowable框架入门步骤

    springboot整合flowable框架入门步骤

    最近工作中有用到工作流的开发,引入了flowable工作流框架,在此记录一下springboot整合flowable工作流框架的过程,感兴趣的朋友一起看看吧
    2022-04-04
  • SpringBoot部署和前端连接问题解决的完整指南(net::ERR_CONNECTION_REFUSED)

    SpringBoot部署和前端连接问题解决的完整指南(net::ERR_CONNECTION_REFUSED)

    在开发和部署 Spring Boot 应用时,可能会遇到各种问题,例如 JAR 文件无法运行、前端无法连接后端服务等,本文将详细总结这些问题的解决方法,帮助你顺利部署和运行 Spring Boot 应用,需要的朋友可以参考下
    2025-01-01
  • Java 异常详解

    Java 异常详解

    本文主要介绍了异常与错误的区别,异常的体现分类,异常的处理机制,如何自定义异常等,具有很好的参考价值,下面跟着小编一起来看下吧
    2017-02-02
  • Java零基础也看得懂的单例模式与final及抽象类和接口详解

    Java零基础也看得懂的单例模式与final及抽象类和接口详解

    本文主要讲了单例模式中的饿汉式和懒汉式的区别,final的使用,抽象类的介绍以及接口的具体内容,感兴趣的朋友来看看吧
    2022-05-05
  • Shell重启SpringBoot项目脚本的示例代码(含服务守护)

    Shell重启SpringBoot项目脚本的示例代码(含服务守护)

    本文介绍了如何使用 Bash 脚本来管理和守护运行服务,将展示一个示例脚本,该脚本可以停止、启动和守护运行一个服务,并提供了相应的解释和用法说明,文章通过代码示例介绍的非常详细,需要的朋友可以参考下
    2023-11-11
  • spring boot整合mongo查询converter异常排查记录

    spring boot整合mongo查询converter异常排查记录

    这篇文章主要为大家介绍了spring boot整合mongo查询时抛出converter异常的排查解决记录,有需要的朋友可以借鉴参考下,希望能够有所帮助
    2022-03-03
  • java String类常用方法练习小结

    java String类常用方法练习小结

    本文主要介绍了java String类常用方法的例子,具有很好的参考价值,下面跟着小编一起来看下吧
    2017-02-02

最新评论