java Spring authorization Sever custom UserDetails JSON反序列化问题

bvuwiixz  于 2023-04-04  发布在  Java
关注(0)|答案(1)|浏览(165)

我现在正通过尝试从Keycloak迁移到Spring Authorization Server来与JSON反序列化斗争一段时间(我仍然怀疑这是否是一个好主意)。
首先尝试使用代码授权类型获取访问令牌,在使用CustomUserDetails时出现了异常

Caused by: java.lang.IllegalArgumentException: The class with com.company.user.CustomUserDetails and name of com.company.user.CustomUserDetails is not in the allowlist. If you believe this class is safe to deserialize, please provide an explicit mapping using Jackson annotations or by providing a Mixin. If the serialization is only done by a trusted source, you can also enable default typing. See https://github.com/spring-projects/spring-security/issues/4370 for details

我访问了https://github.com/spring-projects/spring-security/issues/4370链接,但没有什么真正有用的。
根据错误消息,我定义了此CustomUserDetailsMixin

@JsonTypeInfo(use = JsonTypeInfo.Id.CLASS, include = JsonTypeInfo.As.PROPERTY)
@JsonDeserialize(using = CustomUserDetailsSerializer.class)
@JsonAutoDetect(fieldVisibility = JsonAutoDetect.Visibility.ANY, getterVisibility = JsonAutoDetect.Visibility.NONE,
        isGetterVisibility = JsonAutoDetect.Visibility.NONE)
@JsonIgnoreProperties(ignoreUnknown = true)
public abstract class CustomUserDetailsMixin {
}

CustomUserDetailsSerializer

public class CustomUserDetailsSerializer extends JsonDeserializer<CustomUserDetails> {
    private static final TypeReference<Set<SimpleGrantedAuthority>> SIMPLE_GRANTED_AUTHORITY_SET = new TypeReference<>() {
    };

    @Override
    public CustomUserDetails deserialize(JsonParser jp, DeserializationContext ctxt) throws IOException, JsonProcessingException {
        ObjectMapper mapper = (ObjectMapper) jp.getCodec();
        JsonNode jsonNode = mapper.readTree(jp);

        //there is an issue here :
        Set<? extends GrantedAuthority> authorities = mapper.convertValue(jsonNode.get("authorities"), SIMPLE_GRANTED_AUTHORITY_SET);
    }
}

在这里注册:

@Configuration(proxyBeanMethods = false)
public class AuthorizationServerConfiguration {

    @Bean 
    public OAuth2AuthorizationService oAuth2AuthorizationService(JdbcTemplate jdbcTemplate, RegisteredClientRepository registeredClientRepository) {
        JdbcOAuth2AuthorizationService oAuth2AuthorizationService = new JdbcOAuth2AuthorizationService(jdbcTemplate, registeredClientRepository);
        JdbcOAuth2AuthorizationService.OAuth2AuthorizationRowMapper rowMapper = new JdbcOAuth2AuthorizationService.OAuth2AuthorizationRowMapper(registeredClientRepository);
        ClassLoader classLoader = JdbcOAuth2AuthorizationService.class.getClassLoader();
        ObjectMapper objectMapper = new ObjectMapper();
        objectMapper.registerModules(new CoreJackson2Module());
        objectMapper.registerModules(SecurityJackson2Modules.getModules(classLoader));
        objectMapper.registerModule(new OAuth2AuthorizationServerJackson2Module());

        //registering the mixin
        objectMapper.addMixIn(CustomUserDetails.class, CustomUserDetailsMixin.class);

        rowMapper.setObjectMapper(objectMapper);
        oAuth2AuthorizationService.setAuthorizationRowMapper(rowMapper);
        return oAuth2AuthorizationService;
    }

}

但现在我又犯了一个错误:

java.lang.IllegalArgumentException: Could not resolve type id 'java.util.ImmutableCollections$ListN' as a subtype of `java.util.Set<org.springframework.security.core.authority.SimpleGrantedAuthority>`: Not a subtype
 at [Source: UNKNOWN; byte offset: #UNKNOWN]
    at org.springframework.security.oauth2.server.authorization.JdbcOAuth2AuthorizationService$OAuth2AuthorizationRowMapper.parseMap(JdbcOAuth2AuthorizationService.java:467)

我看了一下spring security保存在db中的JSON,它看起来像这样:

{
  "@class": "java.util.Collections$UnmodifiableMap",
  "java.security.Principal": {
    "@class": "org.springframework.security.authentication.UsernamePasswordAuthenticationToken",
    "authorities": [
      "java.util.Collections$UnmodifiableRandomAccessList",
      [
        {
          "@class": "org.springframework.security.core.authority.SimpleGrantedAuthority",
          "authority": "ROLE_USER"
        }
      ]
    ],
   }
  ....
}

问题是如何解决最后一个错误?

mefy6pfw

mefy6pfw1#

json中的“java.util.Collections$UnmodifiableRandomAccessList”类型信息与您的SIMPLE_GRANTED_AUTHORITY_SET类型引用不兼容,因此有一种简单的方法来处理。
使用已经在CoreJackson 2 Module中注册的类型引用,然后将其转换为实际需要的类型。

TypeReference<List<SimpleGrantedAuthority>> listType = new TypeReference<>() {
        };

        List<SimpleGrantedAuthority> authoritiesList = mapper.convertValue(jsonNode.get("authorities"), listType);
        Set<? extends SimpleGrantedAuthority> authorities = authoritiesList.stream().collect(Collectors.toSet());

相关问题