两种OAuth2AccessToken获取方式的过期问题及解决方案咨询
问题分析与解决方案
问题原因
第一种方式自动刷新的原理
@RegisteredOAuth2AuthorizedClient注解由Spring Security的OAuth2AuthorizedClientArgumentResolver负责解析,这个解析器内部会通过OAuth2AuthorizedClientManager完成令牌有效性校验:
- 检测到令牌过期时,会自动调用配置好的刷新逻辑获取新令牌
- 但该解析器仅作用于Controller方法参数注入场景,无法在过滤器/拦截器中直接复用这一逻辑
第二种方式返回旧令牌的原因
OAuth2AuthorizedClientService的核心职责是持久化和读取授权客户端数据,它本身不具备令牌过期校验和自动刷新能力:
- 调用
loadAuthorizedClient()时,只会直接返回存储中已有的旧数据 - 即使令牌已过期,也不会主动触发刷新流程,所以拿到的始终是过期令牌
解决方案:在过滤器中集成令牌自动刷新逻辑
要在过滤器中实现和@RegisteredOAuth2AuthorizedClient一致的自动刷新效果,需直接使用OAuth2AuthorizedClientManager管理授权客户端,而非直接调用OAuth2AuthorizedClientService。
步骤1:配置OAuth2AuthorizedClientManager
在配置类中定义OAuth2AuthorizedClientManager的Bean,它会自动整合令牌刷新逻辑:
@Configuration public class OAuth2ClientConfig { @Bean public OAuth2AuthorizedClientManager authorizedClientManager( ClientRegistrationRepository clientRegistrationRepository, OAuth2AuthorizedClientService authorizedClientService) { OAuth2AuthorizedClientProvider authorizedClientProvider = OAuth2AuthorizedClientProviderBuilder.builder() .authorizationCode() .refreshToken() // 启用刷新令牌支持 .build(); DefaultOAuth2AuthorizedClientManager authorizedClientManager = new DefaultOAuth2AuthorizedClientManager( clientRegistrationRepository, authorizedClientService); authorizedClientManager.setAuthorizedClientProvider(authorizedClientProvider); return authorizedClientManager; } }
步骤2:改造过滤器使用OAuth2AuthorizedClientManager
修改过滤器,注入OAuth2AuthorizedClientManager,通过它获取授权客户端,自动处理令牌过期刷新:
@Component public class TestFilter implements Filter { private final OAuth2AuthorizedClientManager authorizedClientManager; // 构造注入(推荐替代@Autowired) public TestFilter(OAuth2AuthorizedClientManager authorizedClientManager) { this.authorizedClientManager = authorizedClientManager; } @Override public void doFilter(ServletRequest servletRequest, ServletResponse servletResponse, FilterChain filterChain) throws IOException, ServletException { HttpServletRequest request = (HttpServletRequest) servletRequest; OAuth2AuthenticationToken authentication = (OAuth2AuthenticationToken) SecurityContextHolder.getContext().getAuthentication(); // 构建客户端授权请求 OAuth2AuthorizeRequest authorizeRequest = OAuth2AuthorizeRequest.withClientRegistrationId("azure") .principal(authentication) .build(); // 由manager处理令牌校验与刷新,返回有效令牌 OAuth2AuthorizedClient authorizedClient = authorizedClientManager.authorize(authorizeRequest); if (authorizedClient != null) { servletRequest.setAttribute("access-token", authorizedClient.getAccessToken()); } filterChain.doFilter(servletRequest, servletResponse); } }
关键说明
OAuth2AuthorizedClientManager会自动检查令牌是否过期,若过期且存在有效刷新令牌,会自动调用授权服务器刷新令牌,并将新令牌更新到OAuth2AuthorizedClientService的存储中- 这种方式和
@RegisteredOAuth2AuthorizedClient使用同一套逻辑,保证了令牌处理的一致性 - 可将该过滤器封装为通用组件,在多服务中直接复用
内容的提问来源于stack exchange,提问作者Turik Mirash
相关产品推荐
相关产品推荐

