解决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.verter.FormHttpMessageConverter"/>
<bean class="cn.autodxmon.jsonView.ViewAwareJsonMessageConverter">
</bean>
<bean class="org.verter.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.verter.AbstractHttpMessageConverter.write过程中,⼜要判断Content-Type不能含有通配符,这应该是⼀种保护机制,并强制⽤户⾃⼰配置MediaType。代码如下:
@Override
public final void write(final T t, MediaType contentType, HttpOutputMessage outputMessage)
throws IOException, HttpMessageNotWritableException {
final HttpHeaders headers = Headers();
if (ContentType() == 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);
}
}
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, String());
}
所以,需要为ViewAwareJsonMessageConverter设置supportedMediaTypes:
<bean class="cn.autodxmon.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常用方法这是fastjson做了⼀个性能优化,将排序需求抽象出⼀个SerializerFeature,供⽤户⾃⼰配置。如果需要排序场景,在序列化时添加参数SerializerFeature.MapSortField即可,即:
官⽅⽂档
1.2.3之后的版本,Map的序列化没有做排序再输出,原因是通过TreeMap排序很影响性能。
1.2.27版本中增加SerializerFeature.MapSortField实现同样的功能。
使⽤⽅法如下:
a) 传⼊SerializerFeature.MapSortField参数。 JSONString(map, SerializerFeature.MapSortField);
b) 通过代码修改全局缺省配置。 JSON.DEFAULT_GENERATE_FEATURE |= Mask();
c) 通过JVM启动参数配置修改全局配置 -Dfastjson.serializerFeatures.MapSortField=true
d) 通过类路径下的fastjson.properties来配置 fastjson.serializerFeatures.MapSortField=true
新⽼版本序列化和反序列化不兼容,会出乱码。
更多关于fastjson的相关⽂章请点击下⾯的相关链接
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论