springboot使用FastJson替換Redis的預設序列方式實現物件的序列化,及autoType is not support的解決辦法
阿新 • • 發佈:2018-12-09
自定義Redis的序列化方式需要實現 RedisSerializer<T> 這個介面
public interface RedisSerializer<T> {
@Nullable
byte[] serialize(@Nullable T t) throws SerializationException;
@Nullable
T deserialize(@Nullable byte[] bytes) throws SerializationException;
}
FastJson序列化器實現:
public 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 (T) JSON.parseObject(str, clazz); } }
設定RedisTemplate及序列化方式
@Bean public RedisSerializer<Object> fastJson2JsonRedisSerializer() { return new FastJson2JsonRedisSerializer<Object>(Object.class); } @Bean public RedisTemplate<String, Object> redisTemplate(RedisConnectionFactory redisCF) { RedisTemplate<String, Object> redisTemplate = new RedisTemplate<String, Object>(); redisTemplate.setConnectionFactory(redisCF); redisTemplate.setKeySerializer(new StringRedisSerializer()); redisTemplate.setValueSerializer(fastJson2JsonRedisSerializer()); redisTemplate.afterPropertiesSet(); return redisTemplate; }
注意事項:
2017年3月15日,fastjson官方釋出安全升級公告,該公告介紹fastjson在1.2.24及之前的版本存在程式碼執行漏洞,當惡意攻擊者提交一個精心構造的序列化資料到服務端時,由於fastjson在反序列化時存在漏洞,可導致遠端任意程式碼執行。自1.2.25及之後的版本,禁用了部分autotype的功能,也就是@type這種指定型別的功能會被限制在一定範圍內使用。而由於反序列化物件時,需要檢查是否開啟了autotype。所以如果反序列化檢查時,autotype沒有開啟,就會報錯。所以採用上述序列化方式時需要在專案配置fastjson時配置autotype相關內容本文選擇在程式碼中配置其他方式請參考:
@Bean
public HttpMessageConverters fastJsonHttpMessageConverters() {
FastJsonHttpMessageConverter fastConverter = new FastJsonHttpMessageConverter();
FastJsonConfig fastJsonConfig = new FastJsonConfig();
fastJsonConfig.setSerializerFeatures(SerializerFeature.PrettyFormat);
fastConverter.setFastJsonConfig(fastJsonConfig);
//必須加否則會報com.alibaba.fastjson.JSONException: autoType is not sup這個錯
ParserConfig.getGlobalInstance().addAccept("需要序列化物件的包");
HttpMessageConverter<?> converter = fastConverter;
return new HttpMessageConverters(converter);
}
到此完成配置,專案中應用如下:
@Autowired
private RedisTemplate<String, Object> redisTemplate;
@RequestMapping(value = "set")
public void set() {
UserInfo user = new UserInfo(1, "張三", "18758974838", new Date());
redisTemplate.opsForValue().set("user", user);
System.out.println(redisTemplate.opsForValue().get("user"));
}