当前位置: 首页 > 知识库问答 >
问题:

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

松钊
2023-03-14

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

这是我过去访问用户主体的方式:

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

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

现在我已经更改了令牌存储,getMain()确实返回了User细节对象。我可以忍受这一点,但我想知道为什么这突然改变了——因为这一点,我不得不重构一些代码,因为到目前为止,我一直期望用户名来自get主体()。我也想知道我是否能改变这一点。

在我看来,JdbcTokenStore似乎可以序列化Java对象。它试图序列化标记对象和用户详细信息对象。tokenauthentication列似乎代表了这些序列化对象,我想理解为什么这实际上是必要的。毕竟,这些信息可以在启动/运行时从数据库中恢复。当然除了标记,但我不明白为什么他们不存储标记(字符串),而是存储对象。

最重要的是:对这些类中的任何一个进行最轻微的更改,它们都不会被反序列化!如果其中一个类被更改,每个用户都将被迫重新登录,这与我想首先使用JdbcTokenStore的原因不符——所以一定有可疑的东西,否则我就不知道了。

也许有人能对此有更多的了解。

共有1个答案

吴和硕
2023-03-14

看着你的咆哮,再看看你的代码,我也有点惊讶!它在封面下做的实际上是序列化对象(就像你建议的!)变成一个看起来很不友好的对象字符串:

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

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

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...

}

我实际上还没有尝试或测试上面的代码,您可能不得不摆弄序列化规则,但我只能告诉您这些。

我可以对你这种奇怪的默认行为表示同情,但我不明白你为什么会在这里做错什么。我只能说这么多了!

仅供参考,对于第一个问题,我并不惊讶这些不同的实现可能会返回不同的主体,这对于身份验证实现来说是正常的,而Spring就是这样做的。

 类似资料:
  • 问题内容: “对象序列化”是什么意思?你能用一些例子解释一下吗? 问题答案: 序列化是将对象转换为一系列字节,以便可以将对象轻松保存到持久性存储或跨通信链接进行流传输。然后可以将字节流反序列化-转换为原始对象的副本。

  • 问题内容: 经过数小时的搜索,我终于意识到java.sql.ResultSet无法序列化,也没有办法。我尝试添加到列表中,作为Serializable对象和其他内容中的实例变量,但事实证明这只是幼稚而绝望的尝试。我试图使用的实现的RowSet像对CachedRowSetImpl是序列化,但它们增加了响应时间,最有可能是因为他们迭代ResultSet中。最重要的是,除非选择迭代ResultSet,否

  • 如果接口只是一个标记接口,用于在 java 中传递有关类的某种元数据 - 我有点困惑: 在阅读了java的序列化算法(元数据从下到上,然后从上到下的实际实例数据)的过程之后,我无法真正理解哪些数据不能通过该算法进行处理。 简而言之: 哪些数据可能导致? 我怎么知道我不应该为我的类添加子句?

  • 序列化就是一种用来处理对象流的机制。将对象的内容流化,将流化后的对象传输于网络之间。 序列化是通过实现serializable接口,该接口没有需要实现的方法,implement Serializable只是为了标注该对象是可被序列化的,使用一个输出流(FileOutputStream)来构造一个ObjectOutputStream对象,接着使用ObjectOutputStream对象的writeO

  • 问题内容: 当您使用Exception类扩展一个类(用于创建新的异常)时,会收到警告,提示您有一个。我知道这在序列化和反序列化过程中起着重要的作用,但是何时需要序列化我的Exception?谁能给我一个实际的案例,让我的自定义异常类具有序列化和反序列化? 问题答案: 这是因为所有异常的根类都实现了接口。默认情况下,所有异常都是可序列化的,这是一种语言设计决策,因为作者希望异常能够在没有任何特殊配置

  • 本文向大家介绍Java中的序列化是什么?,包括了Java中的序列化是什么?的使用技巧和注意事项,需要的朋友参考一下 Java提供了一种称为对象序列化的机制,该机制可以将对象表示为字节序列,其中包括对象的数据以及有关对象的类型和存储在对象中的数据类型的信息。 示例