在用户点击登录多次时会出现无法登录认证的情况 后台报错
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;











网友评论