如何配置Spring WebClient实现Access Token复用
问题分析与解决方案
你的核心问题是客户端凭证模式下,WebClient未复用有效期内的Access Token,根源在于默认的OAuth2AuthorizedClientRepository是会话级存储(SessionOAuth2AuthorizedClientRepository),而客户端凭证模式属于应用级授权,需要使用应用级的令牌存储来复用令牌。
原因拆解
- 默认的
ServletOAuth2AuthorizedClientExchangeFilterFunction搭配SessionOAuth2AuthorizedClientRepository时,令牌会绑定到当前HttpSession。如果你的调用场景没有稳定的Session上下文(比如测试用例、定时任务、非Web请求Bean),每次请求都会重新获取令牌。 - 客户端凭证模式的令牌属于应用本身,而非单个用户会话,因此需要用应用级存储来维护已授权的客户端信息,而非会话级存储。
解决方案
1. 配置应用级的OAuth2授权客户端管理器
替换会话级的OAuth2AuthorizedClientRepository为应用级的OAuth2AuthorizedClientService,并构建对应的授权管理器:
@Bean public OAuth2AuthorizedClientManager authorizedClientManager( ClientRegistrationRepository clientRegistrationRepository, OAuth2AuthorizedClientService authorizedClientService) { // 构建客户端凭证模式的授权提供者 OAuth2AuthorizedClientProvider authorizedClientProvider = OAuth2AuthorizedClientProviderBuilder.builder() .clientCredentials() .build(); DefaultOAuth2AuthorizedClientManager authorizedClientManager = new DefaultOAuth2AuthorizedClientManager( clientRegistrationRepository, authorizedClientService); authorizedClientManager.setAuthorizedClientProvider(authorizedClientProvider); return authorizedClientManager; }
2. 基于授权管理器配置WebClient
使用上述OAuth2AuthorizedClientManager创建过滤器,替代原有的会话级配置:
@Bean WebClient webClient(WebClient.Builder builder, OAuth2AuthorizedClientManager authorizedClientManager) { ServletOAuth2AuthorizedClientExchangeFilterFunction oauthFilter = new ServletOAuth2AuthorizedClientExchangeFilterFunction(authorizedClientManager); oauthFilter.setDefaultClientRegistrationId("khtest"); return builder.filter(oauthFilter).build(); }
3. 关键说明
DefaultOAuth2AuthorizedClientService是Spring提供的默认应用级令牌存储(内存实现),会自动维护已获取的令牌,在令牌有效期内复用,过期时自动刷新。- 若需要持久化令牌(比如分布式场景),可以自定义实现
OAuth2AuthorizedClientService,将令牌存储到Redis或数据库中。
验证方式
修改配置后,连续调用两次WebClient请求,查看日志:
- 第一次请求会触发令牌获取请求;
- 第二次请求会直接复用已存在的有效令牌,不再发起新的令牌请求。
内容的提问来源于stack exchange,提问作者Kristina
相关产品推荐
相关产品推荐

