带有访问/刷新令牌的 Spring Boot OAuth2 SSO 未正确存储在数据库中

Posted

技术标签:

【中文标题】带有访问/刷新令牌的 Spring Boot OAuth2 SSO 未正确存储在数据库中【英文标题】:Spring Boot OAuth2 SSO with access/refresh tokens is not stored in a database correctly 【发布时间】:2016-04-26 18:44:03 【问题描述】:

基于此示例https://spring.io/guides/tutorials/spring-boot-oauth2/,我已经通过社交网络实现了使用 SSO 的应用程序。为了改进这种方法并在我的数据库中存储访问/刷新令牌,我添加了oauth_client_token 表:

    CREATE TABLE IF NOT EXISTS oauth_client_token (
      token_id VARCHAR(255),
      token BLOB,
      authentication_id VARCHAR(255),
      user_name VARCHAR(255),
      client_id VARCHAR(255),
      PRIMARY KEY(authentication_id)
    );

并扩展ClientResources 类,以便从AuthorizationCodeResourceDetails.isClientOnly() 方法返回true

class ClientResources 

        private OAuth2ProtectedResourceDetails client = new AuthorizationCodeResourceDetails() 

            @Override
            public boolean isClientOnly() 
                return true;
            

        ;
        private ResourceServerProperties resource = new ResourceServerProperties();

        public OAuth2ProtectedResourceDetails getClient() 
            return client;
        

        public ResourceServerProperties getResource() 
            return resource;
        

    

这是我的 SSO 过滤器:

    private Filter ssoFilter(ClientResources client, String path) 
        OAuth2ClientAuthenticationProcessingFilter clientFilter = new OAuth2ClientAuthenticationProcessingFilter(path);
        OAuth2RestTemplate oAuth2RestTemplate = new OAuth2RestTemplate(client.getClient(), oauth2ClientContext);

        AccessTokenProviderChain tokenProviderChain = new AccessTokenProviderChain(new ArrayList<>(Arrays.asList(new AuthorizationCodeAccessTokenProvider())));
        tokenProviderChain.setClientTokenServices(new JdbcClientTokenServices(dataSource));
        oAuth2RestTemplate.setAccessTokenProvider(tokenProviderChain);

        clientFilter.setRestTemplate(oAuth2RestTemplate);
        clientFilter.setTokenServices(new OkUserInfoTokenServices(okService, client.getClient().getClientId(), apiUrl, eventService));
        clientFilter.setAuthenticationSuccessHandler(new UrlParameterAuthenticationHandler());
        return clientFilter;
    

现在我不确定我是否以正确的方式实现了这个逻辑,而不是肮脏的 hack。

如果我以正确的方式实现了这个东西,请告诉我。

更新

我现在确定这不是正确的实现,因为对于我的表 oauth_client_token 中的 2 个不同的用户,我只有一条记录.. Auth 对象为 null 并且 authentication_id 仅基于 OAuth2 client_id 计算.. 这是错误的。当身份验证不为空时,我需要保留令牌.. 但我不知道如何使用OAuth2ClientAuthenticationProcessingFilter 的当前实现来做到这一点

目前在 spring-security-oauth2 2.0.8.RELEASE 的当前版本中,OAuth2ClientAuthenticationProcessingFilter.successfulAuthentication 方法中只有一个奇怪的注释:

@Override
    protected void successfulAuthentication(HttpServletRequest request, HttpServletResponse response,
            FilterChain chain, Authentication authResult) throws IOException, ServletException 
        super.successfulAuthentication(request, response, chain, authResult);
        // Nearly a no-op, but if there is a ClientTokenServices then the token will now be stored
        restTemplate.getAccessToken();
    

如何正确实现?

【问题讨论】:

【参考方案1】:

在 GitHub 上发现了同样的问题:

https://github.com/spring-projects/spring-security-oauth/issues/498 https://github.com/spring-projects/spring-security-oauth/pull/499

【讨论】:

以上是关于带有访问/刷新令牌的 Spring Boot OAuth2 SSO 未正确存储在数据库中的主要内容,如果未能解决你的问题,请参考以下文章

使用刷新令牌时 Spring Boot JWT 令牌无效签名

如何在 Spring Boot 中实现刷新令牌

Spring 5,401 返回后带有 Google 刷新访问令牌的 OAuth2

带有加密 JWT 访问令牌的 Spring Boot OAuth2

Spring Boot-无效的访问令牌错误

带有 Spring Boot REST 应用程序的 OAuth2 - 无法使用令牌访问资源