美文网首页
记SpringOAuth2同时登录产生多个Token

记SpringOAuth2同时登录产生多个Token

作者: 胡浩8880 | 来源:发表于2020-04-09 08:38 被阅读0次

在用户点击登录多次时会出现无法登录认证的情况 后台报错

org.springframework.security.oauth2.common.exceptions.OAuth2Exception: Incorrect result size: expected 1, actual 6

问题是创建Token的时候出现了并发,所导致的 github上也有相关的讨论

产生问题的代码

DefaultTokenServices createAccessToken的方法没有控制并发所导致的

public class DefaultTokenServices implements AuthorizationServerTokenServices, ResourceServerTokenServices, ConsumerTokenServices, InitializingBean {

private int refreshTokenValiditySeconds = 2592000;

private int accessTokenValiditySeconds = 43200;

private boolean supportRefreshToken = false;

private boolean reuseRefreshToken = true;

private TokenStore tokenStore;

private ClientDetailsService clientDetailsService;

private TokenEnhancer accessTokenEnhancer;

private AuthenticationManager authenticationManager;

public DefaultTokenServices() {

}

public void afterPropertiesSet() throws Exception {

Assert.notNull(this.tokenStore, "tokenStore must be set");

}

@Transactional

public OAuth2AccessToken createAccessToken(OAuth2Authentication authentication) throws AuthenticationException {

OAuth2AccessToken existingAccessToken = this.tokenStore.getAccessToken(authentication);

OAuth2RefreshToken refreshToken = null;

if (existingAccessToken != null) {

if (!existingAccessToken.isExpired()) {

this.tokenStore.storeAccessToken(existingAccessToken, authentication);

return existingAccessToken;

}

TokenStore的实现我选用的是JdbcTokenStore 然后

可以自定义一个CustomTokenServices, 实现createAccessToken方法 ,事务隔离级别设置成序列化.

class CustomTokenServices extends DefaultTokenServices {

@Transactional(rollbackFor = Exception.class, isolation = Isolation.SERIALIZABLE)

@Override

public OAuth2AccessToken createAccessToken( OAuth2Authentication authentication) throws AuthenticationException {

return super.createAccessToken(authentication);

}

}

当然也可以通过synchronized关键字

class CustomTokenServices extends DefaultTokenServices {

@Override

public synchronized OAuth2AccessToken createAccessToken( OAuth2Authentication authentication) throws AuthenticationException {

return super.createAccessToken(authentication);

}

}

最后选用的方案是

ALTER TABLE oauth_access_token ADD unique (authentication_id);

后记:

OAuth2版本

<dependency>

<groupId>org.springframework.security.oauth</groupId>

<artifactId>spring-security-oauth2</artifactId

<version>2.0.14.RELEASE</version>

</dependency>

JdbcTokenStore 的sql

Drop table if exists oauth_access_token;

create table oauth_access_token (

create_time timestamp default now(),

token_id VARCHAR(255),

token BLOB,

authentication_id VARCHAR(255),

user_name VARCHAR(255),

client_id VARCHAR(255),

authentication BLOB,

refresh_token VARCHAR(255)

) ENGINE=InnoDB DEFAULT CHARSET=utf8;

Drop table if exists oauth_refresh_token;

create table oauth_refresh_token (

create_time timestamp default now(),

token_id VARCHAR(255),

token BLOB,

authentication BLOB

) ENGINE=InnoDB DEFAULT CHARSET=utf8;

相关文章

网友评论

      本文标题:记SpringOAuth2同时登录产生多个Token

      本文链接:https://www.haomeiwen.com/subject/ffcqmhtx.html