解决fastjson从1.1.41升级到1.2.28后报错问题详解
最近因为fastjson安全漏洞,升级jar包时,踩了一些坑。
新版本FastJsonHttpMessageConverter初始化,默认设置MediaType为*/*
背景:
使用SpringRestTemplate,配置如下:
text/html;charset=UTF-8 application/json text/javascript;charset=utf-8
其中ViewAwareJsonMessageConverter继承自FastJsonHttpMessageConverter。
fastjson从1.1.41升级到1.2.28之后,请求报错:
jsonjava.lang.IllegalArgumentException:'Content-Type'cannotcontainwildcardtype'*'
原因是在1.1.41中,FastJsonHttpMessageConverter初始化时,设置了MediaType。
publicFastJsonHttpMessageConverter(){ super(newMediaType("application","json",UTF8),newMediaType("application","*+json",UTF8)); }
而在1.2.28中,设置的MediaType为‘/',即:
publicFastJsonHttpMessageConverter(){ super(MediaType.ALL);//*/* }
后续在org.springframework.http.converter.AbstractHttpMessageConverter.write过程中,又要判断Content-Type不能含有通配符,这应该是一种保护机制,并强制用户自己配置MediaType。代码如下:
@Override publicfinalvoidwrite(finalTt,MediaTypecontentType,HttpOutputMessageoutputMessage) throwsIOException,HttpMessageNotWritableException{ finalHttpHeadersheaders=outputMessage.getHeaders(); if(headers.getContentType()==null){ MediaTypecontentTypeToUse=contentType; if(contentType==null||contentType.isWildcardType()||contentType.isWildcardSubtype()){ contentTypeToUse=getDefaultContentType(t); } if(contentTypeToUse!=null){ //设置Content-Type,不允许含有通配符 headers.setContentType(contentTypeToUse); } } ...... if(outputMessageinstanceofStreamingHttpOutputMessage){ ...... }else{ //自定义MessageConverter的write操作 writeInternal(t,outputMessage); outputMessage.getBody().flush(); } } publicvoidsetContentType(MediaTypemediaType){ Assert.isTrue(!mediaType.isWildcardType(),"'Content-Type'cannotcontainwildcardtype'*'"); Assert.isTrue(!mediaType.isWildcardSubtype(),"'Content-Type'cannotcontainwildcardsubtype'*'"); set(CONTENT_TYPE,mediaType.toString()); }
所以,需要为ViewAwareJsonMessageConverter设置supportedMediaTypes:
application/json;charset=UTF-8 application/*+json;charset=UTF-8
新版本序列化默认不再对字段进行排序
这个是一个签名算法的场景:客户端对参数进行序列化,然后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的相关文章请点击下面的相关链接
声明:本文内容来源于网络,版权归原作者所有,内容由互联网用户自发贡献自行上传,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任。如果您发现有涉嫌版权的内容,欢迎发送邮件至:czq8825#qq.com(发邮件时,请将#更换为@)进行举报,并提供相关证据,一经查实,本站将立刻删除涉嫌侵权内容。