我所在的项目组是使用的微服务架构,我们组只负责我们自有模块,其他模块由其他团队负责,有一天,看到一条新闻说是fastjson修复了一些高危漏洞,然后我们就协定升版本,然后今天就踩到了这个坑,报错如下:
com.alibaba.fastjson.JSONException: unclosed.str
1.问题展示
问题是这样的,我们原有代码转换的时候一个json字符串处理如下
String str = "{‘@type‘:‘com.dcf.platform.token.MessageHolder‘,‘forSend‘:‘211554‘,‘generateTime‘:1490422777204,‘id‘:‘18701762172‘,‘lastCanSendTime‘:1490422777204,‘message‘:‘211554‘}";
Object obj = JSON.parse(str);
当这个json字符串转化为object的时候,autotype被fastjson禁用掉了,导致异常
2、问题处理
按照fastjson官网(就是最上面那个链接里)的说法,有几种处理方式,我们就临时先做了一个简单粗暴的处理,等到周一之后讨论具体方案(因为今天是周六)
做法就是按照官网说法,在tomcat的catalina.sh里面的JAVA_OPTS参数后面添加了JVM启动参数:
-Dfastjson.parser.autoTypeSupport=true
这样子就不会报错了,不过这只是临时做法,因为这个是fastjson的安全漏洞,如果按照这种方式的话,也还是存在这样的漏洞的
3、另一种相对较好的解决方式
添加配置项:fastjson.properties里面加入
fastjson.parser.autoTypeAccept=com.serol.pojo
问题也可以解决,注意后面的包名是所要转换对象的包名,测试如下:
Person person = new Person("明明", "aa", 21);
final String valueStr = JSON.toJSONString(person, SerializerFeature.WriteClassName);
System.out.println(valueStr);
Object obj = JSON.parse(valueStr);
System.out.println(((Person)obj).getUsername());
这个相对硬编码方式
ParserConfig.getGlobalInstance().addAccept("com.serol.pojo");
的好处是不用去修改原有代码,只需要添加这个配置,相对于修改JVM启动参数的好处是,这个解禁autotype只针对所设置的这个包下的对象,其他的还是不可以转化
4、其他处理
以上是针对已有代码,不愿意去大动干戈,那么如果新写的话,以怎样的方式更好一些呢?
我的做法是,转化时,需要传入所要转化对象的class
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.serol.pojo.Person;
main: System.out.println(((Person)getJsonObject(Person.class)).getUsername());
public static Object getJsonObject(Class> clazz){
Person person = new Person("明明", "aa", 21);//转化json,简单化处理
String valueStr = JSON.toJSONString(person);//转化json,简单化处理
System.out.println(valueStr);
JSONObject obj = JSON.parseObject(valueStr);
return JSONObject.toJavaObject(obj, clazz);
}
这样的话,就完全不用担心那个安全问题了,避免autotype