SpringCloud中利用OAuth2实现客户端单设备登录
在OAuth2生成Token的地方,源码里面会判断Token是否已经存在,如果存在且未过期直接返回旧的Token,如果不存在或已过期,则重新生成一个新的Token
这里做一个改动:不管旧Token是否过期,都重新生成一个新的Token,保证在新客户端登录后,旧客户端上保存的Token立即失效
具体实现:
1、重新实现DefaultTokenServices的createAccessToken方法
import java.util.Date;
import java.util.UUID;
import org.springframework.security.core.AuthenticationException;
import org.springframework.security.oauth2.common.DefaultExpiringOAuth2RefreshToken;
import org.springframework.security.oauth2.common.DefaultOAuth2AccessToken;
import org.springframework.security.oauth2.common.DefaultOAuth2RefreshToken;
import org.springframework.security.oauth2.common.ExpiringOAuth2RefreshToken;
import org.springframework.security.oauth2.common.OAuth2AccessToken;
import org.springframework.security.oauth2.common.OAuth2RefreshToken;
import org.springframework.security.oauth2.provider.OAuth2Authentication;
import org.springframework.security.oauth2.provider.token.DefaultTokenServices;
import org.springframework.security.oauth2.provider.token.TokenEnhancer;
import org.springframework.security.oauth2.provider.token.TokenStore;
import org.springframework.transaction.annotation.Transactional;
public class MyTokenServices extends DefaultTokenServices {
private TokenStore tokenStore;
private TokenEnhancer accessTokenEnhancer;
@Override
public void setTokenStore(TokenStore tokenStore) {
this.tokenStore = tokenStore;
}
@Override
public void setTokenEnhancer(TokenEnhancer accessTokenEnhancer) {
this.accessTokenEnhancer = accessTokenEnhancer;
}
@Override
@Transactional
public OAuth2AccessToken createAccessToken(OAuth2Authentication authentication) throws AuthenticationException {
OAuth2AccessToken existingAccessToken = tokenStore.getAccessToken(authentication);
OAuth2RefreshToken refreshToken = null;
if (existingAccessToken != null) {
//AccessToken存在,删除并重新创建,实现客户端单点登录功能
if (existingAccessToken.getRefreshToken() != null) {
refreshToken = existingAccessToken.getRefreshToken();
// The token store could remove the refresh token when the
// access token is removed, but we want to
// be sure...
tokenStore.removeRefreshToken(refreshToken);
}
tokenStore.removeAccessToken(existingAccessToken);
}
// Only create a new refresh token if there wasn't an existing one
// associated with an expired access token.
// Clients might be holding existing refresh tokens, so we re-use it in
// the case that the old access token
// expired.
if (refreshToken == null) {
refreshToken = createRefreshToken(authentication);
}
// But the refresh token itself might need to be re-issued if it has
// expired.
else if (refreshToken instanceof ExpiringOAuth2RefreshToken) {
ExpiringOAuth2RefreshToken expiring = (ExpiringOAuth2RefreshToken) refreshToken;
if (System.currentTimeMillis() > expiring.getExpiration().getTime()) {
refreshToken = createRefreshToken(authentication);
}
}
OAuth2AccessToken accessToken = createAccessToken(authentication, refreshToken);
tokenStore.storeAccessToken(accessToken, authentication);
// In case it was modified
refreshToken = accessToken.getRefreshToken();
if (refreshToken != null) {
tokenStore.storeRefreshToken(refreshToken, authentication);
}
return accessToken;
}
private OAuth2RefreshToken createRefreshToken(OAuth2Authentication authentication) {
if (!isSupportRefreshToken(authentication.getOAuth2Request())) {
return null;
}
int validitySeconds = getRefreshTokenValiditySeconds(authentication.getOAuth2Request());
String value = UUID.randomUUID().toString();
if (validitySeconds > 0) {
return new DefaultExpiringOAuth2RefreshToken(value, new Date(System.currentTimeMillis()
+ (validitySeconds * 1000L)));
}
return new DefaultOAuth2RefreshToken(value);
}
private OAuth2AccessToken createAccessToken(OAuth2Authentication authentication, OAuth2RefreshToken refreshToken) {
DefaultOAuth2AccessToken token = new DefaultOAuth2AccessToken(UUID.randomUUID().toString());
int validitySeconds = getAccessTokenValiditySeconds(authentication.getOAuth2Request());
if (validitySeconds > 0) {
token.setExpiration(new Date(System.currentTimeMillis() + (validitySeconds * 1000L)));
}
token.setRefreshToken(refreshToken);
token.setScope(authentication.getOAuth2Request().getScope());
return accessTokenEnhancer != null ? accessTokenEnhancer.enhance(token, authentication) : token;
}
}
2、在AuthorizationServerConfigurerAdapter中进行配置
@Override
public void configure(AuthorizationServerEndpointsConfigurer endpoints) {
//使用自定义的TokenServices
MyTokenServices tokenServices = new MyTokenServices();
tokenServices.setTokenStore(endpoints.getTokenStore());
// 这里如果设置为false则不能更新refresh_token,如果需要刷新token的功能需要设置成true
tokenServices.setSupportRefreshToken(false);
// 设置上次RefreshToken是否还可以使用 默认为true
tokenServices.setReuseRefreshToken(false);
tokenServices.setClientDetailsService(endpoints.getClientDetailsService());
tokenServices.setTokenEnhancer(endpoints.getTokenEnhancer());
endpoints.tokenServices(tokenServices);
}

浙公网安备 33010602011771号