Spring oauth2.0 刷新token后设置原token5分钟内继续可用
通过查看DefaultTokenServices中的刷新token方法refreshAccessToken可以看到生成新的token后会调用removeAccessTokenUsingRefreshToken方法,此方法默认会删除存储的相关token信息
private void removeAccessTokenUsingRefreshToken(String refreshToken) { byte[] key = serializeKey(REFRESH_TO_ACCESS + refreshToken); List<Object> results = null; RedisConnection conn = getConnection(); try { conn.openPipeline(); conn.get(key); conn.del(key); results = conn.closePipeline(); } finally { conn.close(); } if (results == null) { return; } byte[] bytes = (byte[]) results.get(0); String accessToken = deserializeString(bytes); if (accessToken != null) { removeAccessToken(accessToken); } }
所以就需要重写该方法设置不立即删除
首先需要自定义tokenStore
public class OAuth2AuthorizationConfiguration extends AuthorizationServerConfigurerAdapter { @Override public void configure(AuthorizationServerEndpointsConfigurer endpoints) { endpoints.accessTokenConverter(new FrameworkAccessTokenConverter()); endpoints.authorizationCodeServices(meiceAuthorizationCodeService) .tokenEnhancer(jwtAccessTokenConverter()) .reuseRefreshTokens(false) // 使用自定义tokenStore管理tongken .tokenStore(meiceTokenStore) .userDetailsService(meiceUserDetailsService) .authenticationManager(authenticationManager) .setClientDetailsService(meiceClientDetailsService); endpoints.allowedTokenEndpointRequestMethods(HttpMethod.GET, HttpMethod.POST); endpoints.exceptionTranslator(new MeiceWebResponseExceptionTranslator()); //使用自定义granter以返回refresh_token.(默认granter不返回) endpoints.tokenGranter(new CompositeTokenGranter(getMeiceTokenGranters())); } }
//自定义tokenStore(其他代码参考org.springframework.security.oauth2.provider.token.store.redis.RedisTokenStore) public class IRedisTokenStore implements TokenStore { @Override public void removeAccessTokenUsingRefreshToken(OAuth2RefreshToken refreshToken) { removeAccessTokenUsingRefreshToken(refreshToken.getValue()); } private void removeAccessTokenUsingRefreshToken(String refreshToken) { String token = (String) this.redisTemplate.opsForValue().get(REFRESH_TO_ACCESS + refreshToken); if (token != null) { //设置刷新后5分钟内继续可用 redisTemplate.expire(ACCESS + token, 300, TimeUnit.SECONDS); } } }
至此Token将在刷新后5分钟过期删除.