Cannot construct instance of `org.springframework.security.core.authority.SimpleGrantedAuthority`

错误描述
com.fasterxml.jackson.databind.exc.InvalidDefinitionException: Cannot construct instance of org.springframework.security.core.GrantedAuthority (no Creators, like default constructor, exist): abstract types either need to be mapped to concrete types, have custom deserializer, or contain additional type information

方法一

  • 通过编写一个自定义的反序列化器解决此问题
class SimpleGrantedAuthorityDeserializer extends StdDeserializer {
    public SimpleGrantedAuthorityDeserializer() {
        super(SimpleGrantedAuthority.class);
    }
    @Override
    public SimpleGrantedAuthority deserialize(JsonParser p, DeserializationContext ctxt) throws IOException, JsonProcessingException {
        JsonNode tree = p.getCodec().readTree(p);
        return new SimpleGrantedAuthority(tree.get("authority").textValue());
    }
}

然后在redis的反序列化使用Jackson2JsonRedisSerializer反序列化,在里面配置ObjectMapper

配置中加上

@Slf4j
@Configuration
@EnableCaching
@ConditionalOnClass(RedisOperations.class)
@EnableConfigurationProperties(RedisProperties.class)
public class RedisConfig extends CachingConfigurerSupport{


    @SuppressWarnings("all")
    @Bean(name = "redisTemplate")
    @ConditionalOnMissingBean(name = "redisTemplate")
    public RedisTemplate redisTemplate(RedisConnectionFactory redisConnectionFactory) {
        RedisSerializer serializer = redisSerializer();
        RedisTemplate redisTemplate = new RedisTemplate<>();
        redisTemplate.setConnectionFactory(redisConnectionFactory);
        redisTemplate.setKeySerializer(new StringRedisSerializer());
        redisTemplate.setValueSerializer(serializer);
        redisTemplate.setHashKeySerializer(new StringRedisSerializer());
        redisTemplate.setHashValueSerializer(serializer);
        redisTemplate.afterPropertiesSet();
        return redisTemplate;
    }

    @Bean
    public RedisSerializer redisSerializer() {
        //创建JSON序列化器
        Jackson2JsonRedisSerializer serializer = new Jackson2JsonRedisSerializer<>(Object.class);
        ObjectMapper objectMapper = new ObjectMapper();
        objectMapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
        //必须设置,否则无法将JSON转化为对象,会转化成Map类型
        objectMapper.activateDefaultTyping(LaissezFaireSubTypeValidator.instance,ObjectMapper.DefaultTyping.NON_FINAL);
        // 解决jackson2无法反序列化LocalDateTime的问题
        objectMapper.disable(SerializationFeature.WRITE_DATES_AS_TIMESTAMPS);
        objectMapper.registerModule(new FastJavaTimeModule());
        //解决jackson2无法反序列化SimpleGrantedAuthority问题
        objectMapper.registerModule(new SimpleModule().addDeserializer(
                SimpleGrantedAuthority.class, new SimpleGrantedAuthorityDeserializer()));
        serializer.setObjectMapper(objectMapper);
        return serializer;
    }

    }

最后说下jackson+redis序列化会根据get方法自动序列没有此字段的序列化字段出来,SimpleGrantedAuthority中只有role字段 ,没有authority字段,有getAuthority方法赋值role值。

"org.springframework.security.core.authority.SimpleGrantedAuthority",

{
"role": "sys_log_del",

"authority": "sys_log_del"

}

方法2

其实就是在spring security 权限集合反序列化失败

 @Override
    public Collection getAuthorities() {
        List authorities = new ArrayList<>();
        for (Role role : roles) {
            SimpleGrantedAuthority authority = new SimpleGrantedAuthority(role.getName());
            authorities.add(authority);
        }
        return authorities;
    }

这时候我们就需要自定义一个反序列化的类

public class CustomAuthorityDeserializer extends JsonDeserializer {
    @Override
    public Object deserialize(JsonParser p, DeserializationContext ctxt) throws IOException, JsonProcessingException {
        ObjectMapper mapper = (ObjectMapper) p.getCodec();
        JsonNode jsonNode = mapper.readTree(p);
        LinkedList grantedAuthorities = new LinkedList<>();
        Iterator elements = jsonNode.elements();
        while (elements.hasNext()) {
            JsonNode next = elements.next();
            JsonNode authority = next.get("authority");
            //将得到的值放入链表 最终返回该链表
            grantedAuthorities.add(new SimpleGrantedAuthority(authority.asText()));
        }
        return grantedAuthorities;
    }
}

同时加上一个注解 自定义解析即可生效
@JsonDeserialize(using = CustomAuthorityDeserializer.class)

    @Override
    @JsonDeserialize(using = CustomAuthorityDeserializer.class)
    public Collection getAuthorities() {
        List authorities = new ArrayList<>();
        for (Role role : roles) {
            SimpleGrantedAuthority authority = new SimpleGrantedAuthority(role.getName());
            authorities.add(authority);
        }
        return authorities;
    }

你可能感兴趣的:(Cannot construct instance of `org.springframework.security.core.authority.SimpleGrantedAuthority`)