Oauth2.0 token多线程并行超发问题OAuth2Exception: Incorrect result size: expected 1, actual

OAuth2Exception: Incorrect result size: expected 1, actual 6

问题描述:

多线程并发创建access_token 或者刷新token时,导致oauth_access_token表中,同一个authentication_id出现了多条记录,导致登录时报错OAuth2Exception: Incorrect result size: expected 1, actual 6

maven依赖如下

      <dependency>
            <groupId>org.springframework.security.oauth.boot</groupId>
            <artifactId>spring-security-oauth2-autoconfigure</artifactId>
            <version>2.1.0.RELEASE</version>
        </dependency>

在这里插入图片描述

问题原因

oauth2.0在生成token时,源码的表现是:先判断是否存在token,存在删除,然后新增,但是没有同步锁机制,导致多线程并发出现问题。

解决方式一 重写DefaultTokenServices源码:

1.增加接口锁,在创建和刷新token时增加synchronize

public class CustomTokenServices extends DefaultTokenServices {

    @Override
    public synchronized OAuth2AccessToken createAccessToken( OAuth2Authentication authentication) throws AuthenticationException {
        return super.createAccessToken(authentication);
    }


    @Override
    public synchronized OAuth2AccessToken  refreshAccessToken(String refreshTokenValue, TokenRequest tokenRequest) throws AuthenticationException {
        return super.refreshAccessToken(refreshTokenValue,tokenRequest);
    }
}

2.修改配置类,使其生效

public class OauthServerConfig extends AuthorizationServerConfigurerAdapter {
//增加内容
//    OAuth2的主配置信息,启用防止超发token的代码
    @Override
    public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {

        endpoints.approvalStore(approvalStore());
        endpoints.tokenServices(tokenServices(endpoints));
        endpoints.authenticationManager(authenticationManager);
        endpoints.tokenStore(tokenStore());
        endpoints.authorizationCodeServices(authorizationCodeServices());
        endpoints.userDetailsService(userDetailsService);  //登录的业务逻辑
        endpoints.allowedTokenEndpointRequestMethods(HttpMethod.GET, HttpMethod.POST); //oauth2.0让它支持post也支持get
    }

    /**
     * 重写DefaultTokenServices,添加锁机制,防止超发token
     * @param endpoints
     * @return
     */
    private CustomTokenServices tokenServices(AuthorizationServerEndpointsConfigurer endpoints) {
        CustomTokenServices service=new CustomTokenServices();
        service.setTokenStore(tokenStore());
        service.setSupportRefreshToken(true);       //支持刷新token
        service.setReuseRefreshToken(true);
        service.setClientDetailsService(endpoints.getClientDetailsService());
        service.setTokenEnhancer(endpoints.getTokenEnhancer());
        return service;
    }

}

解决方式二 修改依赖,选择没有这个问题的版本

1. maven依赖修改,认证服务器和资源服务器要一致

  <dependency>
            <groupId>org.springframework.security.oauth</groupId>
            <artifactId>spring-security-oauth2</artifactId>
            <version>2.0.14.RELEASE</version>
        </dependency>

2.资源服务器修改

此时,资源服务器的@EnableOAuth2Sso 失效,需要修改下配置文件,使其对接认证服务器生效

public class ResourceServerConfiguration extends ResourceServerConfigurerAdapter {
// 省略


    @Override
    public void configure(ResourceServerSecurityConfigurer resources) {
   		//重点,使其使用数据库内容,不然认证服务器不会生效
        resources.tokenStore(tokenStore());
    }

    //数据库连接池对象
    @Autowired
    private DataSource dataSource;


    //客户端信息来源
    @Bean
    public JdbcClientDetailsService jdbcClientDetailsService(){
        return new JdbcClientDetailsService(dataSource);
    }

    //token保存策略
    @Bean
    public TokenStore tokenStore(){
        return new JdbcTokenStore(dataSource);
    }

    //授权信息保存策略
    @Bean
    public ApprovalStore approvalStore(){
        return new JdbcApprovalStore(dataSource);
    }

    //授权码模式数据来源
    @Bean
    public AuthorizationCodeServices authorizationCodeServices(){
        return new JdbcAuthorizationCodeServices(dataSource);
    }


}
相关推荐
©️2020 CSDN 皮肤主题: 技术黑板 设计师:CSDN官方博客 返回首页