You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Spring WebClient每次请求资源服务器重复获取访问令牌问题排查

解决OAuth2 Client Credentials模式下访问令牌重复获取问题

你的配置存在三处核心问题,导致每次请求都重新获取令牌:

  • 冗余的oauth2Login配置:你使用的是Client Credentials模式,不需要授权码登录流程,oauth2Login()配置完全多余,还会干扰授权客户端的管理逻辑。
  • 手动传递授权客户端实例:Controller中通过@RegisteredOAuth2AuthorizedClient获取的实例是每次请求新生成的,没有复用缓存的令牌。
  • 未配置令牌缓存机制:默认的内存存储不会自动缓存Client Credentials模式的令牌,需要显式配置授权客户端管理器来处理缓存和自动刷新。

优化步骤

1. 修正Security配置,启用正确的OAuth2客户端支持

移除无用的oauth2Login(),添加Client Credentials模式专属的授权客户端管理器,负责令牌的缓存和自动刷新:

@Configuration(proxyBeanMethods = false)
@EnableWebFluxSecurity
public class SecurityConfig {

    @Bean
    SecurityWebFilterChain springSecurityFilterChain(ServerHttpSecurity http) {
        http.authorizeExchange(exchange -> exchange.anyExchange().permitAll())
            .oauth2Client(withDefaults()); // 启用OAuth2客户端核心支持
        return http.build();
    }

    @Bean
    ReactiveOAuth2AuthorizedClientManager authorizedClientManager(
            ReactiveClientRegistrationRepository clientRegistrationRepository,
            ReactiveOAuth2AuthorizedClientService authorizedClientService) {
        // 配置Client Credentials模式的授权提供者
        ReactiveOAuth2AuthorizedClientProvider authorizedClientProvider =
                ReactiveOAuth2AuthorizedClientProviderBuilder.builder()
                        .clientCredentials()
                        .build();

        // 使用授权客户端服务来管理和缓存令牌
        AuthorizedClientServiceReactiveOAuth2AuthorizedClientManager authorizedClientManager =
                new AuthorizedClientServiceReactiveOAuth2AuthorizedClientManager(
                        clientRegistrationRepository, authorizedClientService);
        authorizedClientManager.setAuthorizedClientProvider(authorizedClientProvider);

        return authorizedClientManager;
    }
}

2. 重构WebClient配置,使用授权客户端管理器

让WebClient通过授权客户端管理器自动处理令牌的获取、缓存和刷新,不再依赖手动传递实例:

@Configuration
public class WebClientConfig {

    @Bean
    WebClient getClient(ReactiveOAuth2AuthorizedClientManager authorizedClientManager) {
        ServerOAuth2AuthorizedClientExchangeFilterFunction oauth =
                new ServerOAuth2AuthorizedClientExchangeFilterFunction(authorizedClientManager);

        oauth.setDefaultClientRegistrationId("salesforce");

        return WebClient.builder()
                .filter(oauth)
                .build();
    }
}

3. 简化Controller逻辑

移除手动传递授权客户端的代码,让WebClient自动完成令牌注入:

@RestController
public class SalesforceController {

    private final WebClient webClient;

    public SalesforceController(WebClient webClient) {
        this.webClient = webClient;
    }

    @GetMapping(value="/order", produces="application/json")
    Mono<String> getOrder() {
        return this.webClient
                .get()
                .uri("https://my.service.com/Order/1")
                .retrieve()
                .bodyToMono(String.class)
                .timeout(Duration.ofSeconds(5));
    }
}

优化后效果

  • 令牌会被ReactiveOAuth2AuthorizedClientService自动缓存,有效期内所有请求复用同一令牌
  • 令牌过期时会自动触发刷新流程,无需手动干预
  • 配置符合Spring Security OAuth2 Client Credentials模式的最佳实践,冗余代码全部清除

内容的提问来源于stack exchange,提问作者Dale Ogilvie

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.17 22:02:26