为什么我的JdbcTokenStore商店序列化Java对象?

问题描述 投票:2回答:1

所以我只是从InMemoryTokenStore转移到JdbcTokenStore。像往常一样,一个看似简单的变化之后是一些副作用,包括吞噬异常 - 抱怨咆哮。

这就是我以前访问用户主体的方式:

Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
String username = (String) authentication.getPrincipal();

First

出于某种原因,getPrincipal()总是只返回用户名而不是UserDetails对象。这对我来说已经足够了,所以我选择了它。

现在我改变了令牌存储,getPrincipal()确实返回了UserDetails对象。我可以忍受这一点,但我想知道为什么这会突然改变 - 我必须重构一些代码,因为我总是期望getPrincipal()的用户名到现在为止。我也想知道我是否可以改变这一点。

Second

从我所看到的,JdbcTokenStore似乎序列化Java对象。它试图序列化Token对象和UserDetails对象。列tokenauthentication似乎代表那些序列化对象,我想了解为什么这实际上是必要的。毕竟这是在数据库启动/运行期间可以恢复的信息。当然除了Token,但我不明白为什么他们不仅存储令牌(String)而是存储对象。

最重要的是:对这些类中的任何一个进行最轻微的改动,它们都不会被反序列化!如果其中一个类被改变了,那么每个用户都将被迫进入新的登录状态,这就是为什么我想首先使用JdbcTokenStore的原因 - 所以必须有一些可疑的东西或者我没有得到它。

enter image description here


也许有人可以对此有所了解。

spring spring-boot spring-security spring-oauth2
1个回答
0
投票

看着你的咆哮,然后看着你的代码,我也有点惊讶!它在幕后所做的实际上是将对象(如你所建议的!)序列化为一个看起来非常不友好的对象字符串:

protected byte[] serializeAccessToken(OAuth2AccessToken token) {
    return SerializationUtils.serialize(token);
}

看起来应该做什么(我不确定为什么他们不在文档中指出这一点),是覆盖*serialize中的JdbcTokenStore方法:

protected OAuth2AccessToken deserializeAccessToken(byte[] token) 
protected OAuth2Authentication  deserializeAuthentication(byte[] authentication) 
protected OAuth2RefreshToken    deserializeRefreshToken(byte[] token) 
protected byte[] serializeAccessToken(OAuth2AccessToken token) 
protected byte[] serializeAuthentication(OAuth2Authentication authentication) 
protected byte[] serializeRefreshToken(OAuth2RefreshToken token)

这可能就是他们受到保护的原因。实现可能看起来像:

class JacksonJdbcTokenStore extends JdbcTokenStore {

    private ObjectMapper mapper;

    public JdbcTokenStore(ObjectMapper mapper, DataSource dataSource) {
        this.mapper = mapper;
        super(dataSource);
    }

    protected byte[] serializeAuthentication(OAuth2Authentication authentication) 
    {
        return mapper.writeValueAsBytes(authentication);
    }

    protected OAuth2Authentication deserializeAuthentication(byte[] authentication) {
        return mapper.read(authentication, OAuth2Authentication.class);
    }

    // Same type of thing for the other serialize/deserialize operations...

}

我实际上没有尝试或测试上面的代码,你可能不得不摆弄序列化规则,但这就是我能告诉你的全部内容。

我可以同意你对这种奇怪的默认行为的陌生感,但我不明白为什么你在这里做错了什么。这是我能说的最好的!

仅供参考,对于第一个问题,我并不感到惊讶,这些不同的实现可能会返回不同的Principal,这对于Authentication实现来说是正常的,而这正是Spring完成它的方式。

© www.soinside.com 2019 - 2024. All rights reserved.