最近在整合redis的时候,发现数据从redis取出后无法强转为原先存入的对象,因为我的HttpMessage解析用的是FastJson,所以为了保持一致,我将RedisSerializer<T>接口实现了,然后主动注入RedisTemplate,将其中的序列化方式指定为FastJson。但是在执行反序列化的最后一步JSON.parseObject(str, clazz);始终提示(autotype is not support),我的类型不支持被强转,然后去查了一下。
2017年3月15日,fastjson官方发布安全升级公告,该公告介绍fastjson在1.2.24及之前的版本存在代码执行漏洞,当恶意攻击者提交一个精心构造的序列化数据到服务端时,由于fastjson在反序列化时存在漏洞,可导致远程任意代码执行。
自1.2.25及之后的版本,禁用了部分autotype的功能,也就是”@type”这种指定类型的功能会被限制在一定范围内使用。
而由于反序列化对象时,需要检查是否开启了autotype。所以如果反序列化检查时,autotype没有开启,就会报错。
阿里提供的解决方法
我的案例
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.serializer.SerializerFeature;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.serializer.RedisSerializer;
import org.springframework.data.redis.serializer.SerializationException;
import org.springframework.data.redis.serializer.StringRedisSerializer;
import java.nio.charset.Charset;
/**
* redis 配置类
*
* @Auther: Tt
* @Date: 2018/11/10 15:35
*/
@Configuration
public class RedisConfig {
RedisConfig(){
//打开autotype功能,需要强转的类一次添加其后
ParserConfig.getGlobalInstance()
.addAccept("com.qiein.wxplat.web.entity.dto.UserCheckDTO");
}
@Bean
public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory factory){
RedisTemplate<String, Object> template = new RedisTemplate<>();
template.setConnectionFactory(factory);
StringRedisSerializer stringRedisSerializer = new StringRedisSerializer();
//设置key采用String的序列化方式
template.setKeySerializer(stringRedisSerializer);
//设置hash的key也采用String的序列化方式
template.setHashKeySerializer(stringRedisSerializer);
FastJson2JsonRedisSerializer fastJson2JsonRedisSerializer =new FastJson2JsonRedisSerializer<Object>(Object.class);
//设置value采用的fastjson的序列化方式
template.setValueSerializer(fastJson2JsonRedisSerializer);
//设置hash的value采用的fastjson的序列化方式
template.setHashValueSerializer(fastJson2JsonRedisSerializer);
//设置其他默认的序列化方式为fastjson
template.setDefaultSerializer(fastJson2JsonRedisSerializer);
template.afterPropertiesSet();
return template;
}
public static 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, SerializerFeature.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);
}
}
}