jackson OAuth2身份验证对象反序列化(RedisTokenStore)

mccptt67  于 2022-11-09  发布在  Redis
关注(0)|答案(1)|浏览(816)

我尝试重写一些旧代码,使用org.springframework.security.oauth2.provider.token.store.InMemoryTokenStore来存储访问令牌。我现在尝试使用RedisTokenStore来代替以前使用的InMemoryTokenStore。令牌被生成并存储在Redis fine(独立的Redis配置)中,但是,OAuth2Authentication的反序列化失败,并出现以下错误:

Could not read JSON: Cannot construct instance of `org.springframework.security.oauth2.provider.OAuth2Authentication` (no Creators, like default constructor, exist): cannot deserialize from Object value (no delegate- or property-based Creator)

由于这个类没有默认的构造函数,所以在Redis中查找时,反序列化和Map到实际对象的操作会失败。

RedisTokenStore redisTokenStore = new RedisTokenStore(jedisConnectionFactory);
redisTokenStore.setSerializationStrategy(new StandardStringSerializationStrategy() {
        @Override    
        protected <T> T deserializeInternal(byte[] bytes, Class<T> aClass) {
            return Utilities.parse(new String(bytes, StandardCharsets.UTF_8),aClass);
        }

        @Override    
        protected byte[] serializeInternal(Object o) {       
            return Objects.requireNonNull(Utilities.convert(o)).getBytes();
        }
});
this.tokenStore = redisTokenStore;

public static <T> T parse(String json, Class<T> clazz) {    
                try {        
                    return OBJECT_MAPPER.readValue(json, clazz);    
                } catch (IOException e) {        
                    log.error("Jackson2Json failed: " + e.getMessage());    
                }    return null;}

            public static String convert(Object data) {    
                try {        
                    return OBJECT_MAPPER.writeValueAsString(data);    
                } catch (JsonProcessingException e) {        
                    log.error("Conversion failed: " + e.getMessage());    
                }    
                return null;
            }

OAuth2Authentication对象是如何在Redis中重新构造的?因为它没有定义默认的构造函数,所以任何基于Jackson的序列化器和对象Map器都不能反序列化它。
同样,序列化工作得很好(因为OAuth2Authentication实现了Serializable接口),令牌在Redis中存储得很好,只是在调用/oauth/check_token时失败。
我遗漏了什么,在Redis中存储访问令牌时如何处理这个问题?

rryofs0p

rryofs0p1#

我通过编写自定义反序列化程序解决了这个问题。它看起来像这样:

import com.fasterxml.jackson.core.JacksonException;
import com.fasterxml.jackson.core.JsonParser;
import com.fasterxml.jackson.databind.DeserializationContext;
import com.fasterxml.jackson.databind.JsonDeserializer;
import com.fasterxml.jackson.databind.module.SimpleModule;
import org.springframework.security.oauth2.core.AuthorizationGrantType;

import java.io.IOException;

public class AuthorizationGrantTypeCustomDeserializer extends JsonDeserializer<AuthorizationGrantType> {

    @Override
    public AuthorizationGrantType deserialize(JsonParser p, DeserializationContext ctxt) throws IOException, JacksonException {
        Root root = p.readValueAs(Root.class);
        return root != null ?  new AuthorizationGrantType(root.value) : new AuthorizationGrantType("");
    }

    private static class Root {
        public String value;
    }

    public static SimpleModule generateModule() {
        SimpleModule authGrantModule = new SimpleModule();
        authGrantModule.addDeserializer(AuthorizationGrantType.class, new AuthorizationGrantTypeCustomDeserializer());
        return authGrantModule;
    }
}

然后,我在objectMapper中注册了反序列化器,稍后jacksonAPI将使用它

ObjectMapper mapper = new ObjectMapper()
                .registerModule(AuthorizationGrantTypeCustomDeserializer.generateModule());

相关问题