Почему мое хранилище JdbcTokenStore сериализует объекты Java? - PullRequest
0 голосов
/ 07 сентября 2018

Так что я просто перехожу с 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, во-первых, поэтому должно быть что-то подозрительное, или я его не получаю.

enter image description here


Может быть, кто-то мог бы пролить больше света на это.

1 Ответ

0 голосов
/ 07 сентября 2018

Глядя на твою напыщенную речь, а затем на твой код, я тоже был немного удивлен! То, что он делает под прикрытием, на самом деле сериализует объекты (как вы предлагаете!) В очень недружелюбно выглядящую строку объекта:

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 это сделал.

...