所以我只是从InMemoryTokenStore
转移到JdbcTokenStore
。像往常一样,一个看似简单的变化之后是一些副作用,包括吞噬异常 - 抱怨咆哮。
这就是我以前访问用户主体的方式:
Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
String username = (String) authentication.getPrincipal();
出于某种原因,getPrincipal()
总是只返回用户名而不是UserDetails
对象。这对我来说已经足够了,所以我选择了它。
现在我改变了令牌存储,getPrincipal()
确实返回了UserDetails
对象。我可以忍受这一点,但我想知道为什么这会突然改变 - 我必须重构一些代码,因为我总是期望getPrincipal()
的用户名到现在为止。我也想知道我是否可以改变这一点。
从我所看到的,JdbcTokenStore
似乎序列化Java对象。它试图序列化Token
对象和UserDetails
对象。列token
和authentication
似乎代表那些序列化对象,我想了解为什么这实际上是必要的。毕竟这是在数据库启动/运行期间可以恢复的信息。当然除了Token
,但我不明白为什么他们不仅存储令牌(String
)而是存储对象。
最重要的是:对这些类中的任何一个进行最轻微的改动,它们都不会被反序列化!如果其中一个类被改变了,那么每个用户都将被迫进入新的登录状态,这就是为什么我想首先使用JdbcTokenStore
的原因 - 所以必须有一些可疑的东西或者我没有得到它。
也许有人可以对此有所了解。
看着你的咆哮,然后看着你的代码,我也有点惊讶!它在幕后所做的实际上是将对象(如你所建议的!)序列化为一个看起来非常不友好的对象字符串:
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完成它的方式。