OAuth2.0刷新访问令牌时的额外验证逻辑实现问询
解决方案
方案1:自定义OAuth2RefreshTokenAuthenticationProvider(推荐)
直接继承官方的OAuth2RefreshTokenAuthenticationProvider,重写其authenticate方法,在生成新访问令牌前插入用户校验逻辑。这种方式无需复制转换器代码,完全复用原有逻辑,维护性更强。
步骤1:实现自定义Provider
@Component public class CustomRefreshTokenAuthProvider extends OAuth2RefreshTokenAuthenticationProvider { private final UserDetailsService userDetailsService; private final AuthenticationManager authenticationManager; // 注入依赖:刷新令牌服务、令牌生成器、用户详情服务、认证管理器 public CustomRefreshTokenAuthProvider(OAuth2RefreshTokenService refreshTokenService, OAuth2TokenGenerator<? extends OAuth2Token> tokenGenerator, UserDetailsService userDetailsService, AuthenticationManager authenticationManager) { super(refreshTokenService, tokenGenerator); this.userDetailsService = userDetailsService; this.authenticationManager = authenticationManager; } @Override public Authentication authenticate(Authentication authentication) throws AuthenticationException { OAuth2RefreshTokenAuthenticationToken refreshTokenAuth = (OAuth2RefreshTokenAuthenticationToken) authentication; // 从刷新令牌中获取存储的用户认证信息 OAuth2Authentication storedAuth = getRefreshTokenService().findById(refreshTokenAuth.getRefreshToken().getTokenValue()) .map(OAuth2RefreshToken::getAuthentication) .orElseThrow(() -> new InvalidGrantException("无效的刷新令牌")); // 获取用户名并执行校验 String username = storedAuth.getName(); UserDetails user = userDetailsService.loadUserByUsername(username); // 调用认证管理器执行用户活跃状态、权限等额外检查 Authentication userAuthentication = new UsernamePasswordAuthenticationToken( user, null, user.getAuthorities() ); authenticationManager.authenticate(userAuthentication); // 校验通过后,继续执行父类逻辑生成新的访问令牌 return super.authenticate(authentication); } }
步骤2:替换默认Provider
根据你的Spring Security版本,将自定义Provider注册到授权服务器的端点配置中:
Spring Security OAuth2 Legacy(旧版)
@Configuration @EnableAuthorizationServer public class AuthServerConfig extends AuthorizationServerConfigurerAdapter { @Autowired private CustomRefreshTokenAuthProvider customRefreshTokenAuthProvider; @Override public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception { // 替换默认的刷新令牌认证Provider endpoints.authenticationProvider(customRefreshTokenAuthProvider); // 其他配置(如tokenStore、clientDetailsService等) } }
Spring Security 6+ OAuth2 Authorization Server
@Bean public SecurityFilterChain authServerSecurityFilterChain(HttpSecurity http) throws Exception { OAuth2AuthorizationServerConfiguration.applyDefaultSecurity(http); http.getConfigurer(OAuth2AuthorizationServerConfigurer.class) .tokenEndpoint(tokenEndpoint -> // 注册自定义Provider tokenEndpoint.authenticationProvider(customRefreshTokenAuthProvider) ); return http.build(); }
方案2:利用OAuth2AuthenticationValidator(适用于Spring Security 5.6+)
如果你的项目使用Spring Security 5.6及以上版本,可以通过自定义OAuth2AuthenticationValidator,在刷新令牌的认证流程中添加用户校验逻辑。
步骤1:实现自定义Validator
@Component public class UserActiveStatusValidator implements OAuth2AuthenticationValidator<OAuth2RefreshTokenAuthenticationToken> { private final UserDetailsService userDetailsService; private final AuthenticationManager authenticationManager; public UserActiveStatusValidator(UserDetailsService userDetailsService, AuthenticationManager authenticationManager) { this.userDetailsService = userDetailsService; this.authenticationManager = authenticationManager; } @Override public OAuth2AuthenticationValidatorResult validate(OAuth2RefreshTokenAuthenticationToken authentication) { // 从刷新令牌关联的认证信息中获取用户名 OAuth2Authentication storedAuth = authentication.getRefreshToken().getAuthentication(); String username = storedAuth.getName(); UserDetails user = userDetailsService.loadUserByUsername(username); try { // 执行用户校验 Authentication userAuth = new UsernamePasswordAuthenticationToken(user, null, user.getAuthorities()); authenticationManager.authenticate(userAuth); return OAuth2AuthenticationValidatorResult.success(); } catch (AuthenticationException e) { // 校验失败,返回错误信息 return OAuth2AuthenticationValidatorResult.failure( new OAuth2Error(OAuth2ErrorCodes.INVALID_GRANT, e.getMessage(), null) ); } } }
步骤2:注册Validator到授权服务器
@Bean public OAuth2AuthorizationManager<OAuth2RefreshTokenAuthenticationToken> refreshTokenAuthManager( OAuth2RefreshTokenService refreshTokenService, List<OAuth2AuthenticationValidator<OAuth2RefreshTokenAuthenticationToken>> validators) { OAuth2RefreshTokenAuthenticationProvider provider = new OAuth2RefreshTokenAuthenticationProvider( refreshTokenService, null // 按需注入tokenGenerator ); provider.setAuthenticationValidators(validators); return provider::authenticate; }
关键说明
- 方案1是最直接且维护性最好的方式,完全复用官方Provider的核心逻辑,仅扩展校验步骤。
- 避免复制
OAuth2RefreshTokenAuthenticationConverter的原因:官方转换器会随Spring Security版本迭代更新,复制代码会导致后续版本升级时出现兼容性问题,增加维护成本。
内容的提问来源于stack exchange,提问作者Filip
相关产品推荐
相关产品推荐

