关于redis使用Jackson2JsonRedisSerializer序列化,反序列化时权限模块报错的问题

Posted DreamCatcher-qin

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了关于redis使用Jackson2JsonRedisSerializer序列化,反序列化时权限模块报错的问题相关的知识,希望对你有一定的参考价值。

报错内容:

Caused by: com.fasterxml.jackson.databind.exc.MismatchedInputException: Cannot deserialize value of type `org.springframework.security.core.authority.SimpleGrantedAuthority` from Array value (token `JsonToken.START_ARRAY`)

redis里存的对应的json格式:

 "authorities": [
            "java.util.ArrayList",
            [
                [
                    "org.springframework.security.core.authority.SimpleGrantedAuthority",
                    
                        "role": "admin",
                        "authority": "admin"
                    
                ],
                [
                    "org.springframework.security.core.authority.SimpleGrantedAuthority",
                    
                        "role": "common",
                        "authority": "common"
                    
                ]
            ]
        ],

原因: 字符串反序列化是,需要对应的对象有空参构造函数

而SimpleGrantedAuthority是只有有参构造,并且被final修饰不能继承重写

解决办法:

需要对该类进行手动进行反序列化

步骤:

第一步:自定义的反序列化器

public class SimpleGrantedAuthorityDeserializer extends StdDeserializer<SimpleGrantedAuthority> 
    public SimpleGrantedAuthorityDeserializer() 
        super(SimpleGrantedAuthority.class);
    
    @Override
    public SimpleGrantedAuthority deserialize(JsonParser p, DeserializationContext ctxt) throws IOException, JsonProcessingException 
        JsonNode jsonNode = p.getCodec().readTree(p);
         Iterator<JsonNode> elements = jsonNode.elements();
        while (elements.hasNext()) 
            JsonNode next = elements.next();
            JsonNode authority = next.get("authority");
            if(ObjectUtils.isEmpty(authority))
                continue;
            

             return new SimpleGrantedAuthority(authority.asText());
        
        return  null;

    

第二步:将构造器加入到ObjectMapper 中

@Bean
@ConditionalOnMissingBean(RedisSerializer.class)
@SuppressWarnings("all")
public RedisSerializer<Object> serializer( ObjectMapper objectMapper) 
   // 使用Jackson2JsonRedisSerializer来序列化和反序列化redis的value值
   Jackson2JsonRedisSerializer<Object> jackson2JsonRedisSerializer = new Jackson2JsonRedisSerializer<>(Object.class);
   // 指定要序列化的域,field,get和set,以及修饰符范围,ANY是都有包括private和public
   objectMapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
   // 指定序列化输入的类型,类必须是非final修饰的,final修饰的类,比如String,Integer等会跑出异常
   objectMapper.activateDefaultTyping(LaissezFaireSubTypeValidator.instance, ObjectMapper.DefaultTyping.NON_FINAL);
   //解决jackson2无法反序列化SimpleGrantedAuthority问题(原因是没有空参构造)
   objectMapper.registerModule(new SimpleModule().addDeserializer(
         SimpleGrantedAuthority.class, new SimpleGrantedAuthorityDeserializer()));

   jackson2JsonRedisSerializer.setObjectMapper(objectMapper);
   return jackson2JsonRedisSerializer;

注意: ObjectMapper 不能new ,只能导入全局的,否则其他位置不生效

其他没有空参够够也会出现该问题,也需要注意

java Redis 关于订阅的使用

 

代码实现

	
	@OnOpen
	public void open(Session session, @PathParam(value = "liveid") String liveid,
			@PathParam(value = "userid") String userid, @PathParam(value = "name") String name) 
		this.session = session;
		logger.error("进入   " + userid);
		
		
		socketServers.forEach(client -> 
			if (client.getUserid().equals(userid)) 
				try 
					logger.error("重复进入断开 " + userid);
					client.getSession().close();
					socketServers.remove(new Client(liveid, userid, name, session));
					socketServers.add(new Client(liveid, userid, name, session));
					return;
				 catch (IOException e) 
					// TODO Auto-generated catch block
					e.printStackTrace();
				
			
		);
		
		socketServers.add(new Client(liveid, userid, name, session));
		
		subscribeListener = new SubscribeListener();
		subscribeListener.setSession(session);
		subscribeListener.setUserid(userid);
		subscribeListener.setName(name);
		subscribeListener.setStringRedisTemplate(redisTampate);
		channeltopic=new ChannelTopic(liveid);
		
		//设置订阅topic
		redisMessageListenerContainer.addMessageListener(subscribeListener,channeltopic);
	

 取消某个订阅

	if(subscribeListener!=null) 
				redisMessageListenerContainer.removeMessageListener(subscribeListener);
				subscribeListener=null;
			

以上是关于关于redis使用Jackson2JsonRedisSerializer序列化,反序列化时权限模块报错的问题的主要内容,如果未能解决你的问题,请参考以下文章

关于python语言使用redis时,连接是否需要关闭的问题

php关于redis的使用方法

关于win7 安装redis的问题

Bitnami Redis 关于 Kubernetes 身份验证失败与现有密钥

关于redis中的zset(sorted set)

java Redis 关于订阅的使用