Spring Security OAuth2 Client令牌端点超时与重试配置咨询
Spring Security OAuth2客户端令牌端点超时与重试配置
一、设置连接/读取超时
Spring Security OAuth2客户端默认通过WebClient调用令牌端点,可通过以下两种方式配置超时:
1. 自定义WebClient配置(精准控制)
创建ClientHttpConnector Bean,指定连接超时和读取超时参数:
import org.springframework.http.client.reactive.ReactorClientHttpConnector; import org.springframework.security.oauth2.client.web.reactive.function.client.ServletOAuth2AuthorizedClientExchangeFilterFunction; import org.springframework.web.reactive.function.client.WebClient; import reactor.netty.http.client.HttpClient; import java.time.Duration; import io.netty.channel.ChannelOption; @Configuration public class OAuth2ClientConfig { @Bean public WebClient oauth2WebClient(ClientRegistrationRepository clientRegistrationRepository, OAuth2AuthorizedClientRepository authorizedClientRepository) { ServletOAuth2AuthorizedClientExchangeFilterFunction oauth2Filter = new ServletOAuth2AuthorizedClientExchangeFilterFunction(clientRegistrationRepository, authorizedClientRepository); oauth2Filter.setDefaultOAuth2AuthorizedClient(true); HttpClient httpClient = HttpClient.create() .responseTimeout(Duration.ofSeconds(10)) // 读取超时 .option(ChannelOption.CONNECT_TIMEOUT_MILLIS, 5000); // 连接超时(毫秒) return WebClient.builder() .filter(oauth2Filter) .clientConnector(new ReactorClientHttpConnector(httpClient)) .build(); } }
2. 全局配置文件(快速生效)
Spring Boot 2.4+支持通过配置文件设置Reactor Netty全局超时,对所有WebClient请求生效:
spring: webflux: client: reactor: netty: connect-timeout: 5s response-timeout: 10s
二、添加令牌端点调用重试
针对令牌端点的超时或临时错误,可通过以下两种方式实现重试:
1. 基于WebClient重试操作符
在自定义WebClient时添加重试逻辑,指定重试触发条件和次数:
// 延续上述WebClient配置,在build阶段添加重试 return WebClient.builder() .filter(oauth2Filter) .clientConnector(new ReactorClientHttpConnector(httpClient)) .filter(ExchangeFilterFunction.ofResponseProcessor(clientResponse -> { // 将服务端错误转为异常,触发重试 if (clientResponse.statusCode().is5xxServerError()) { return clientResponse.createException().flatMap(Mono::error); } return Mono.just(clientResponse); })) .build() .mutate() .filter((request, next) -> next.exchange(request) .retryWhen(Retry.backoff(3, Duration.ofSeconds(1)) .filter(throwable -> throwable instanceof IOException || throwable instanceof WebClientResponseException)) .doOnRetry(retrySignal -> { // 可选:记录重试日志 System.err.println("重试令牌端点调用,原因:" + retrySignal.failure().getMessage()); })) .build();
2. 自定义授权码请求处理器
若需精准控制授权码兑换流程的重试,可自定义ReactiveOAuth2AuthorizationCodeGrantRequestHandler:
import org.springframework.security.oauth2.client.endpoint.OAuth2AuthorizationCodeGrantRequest; import org.springframework.security.oauth2.client.endpoint.ReactiveOAuth2AuthorizationCodeGrantRequestHandler; import org.springframework.security.oauth2.core.OAuth2AccessToken; import reactor.core.publisher.Mono; import reactor.util.retry.Retry; import java.time.Duration; @Component public class RetryableAuthorizationCodeGrantHandler implements ReactiveOAuth2AuthorizationCodeGrantRequestHandler { private final ReactiveOAuth2AuthorizationCodeGrantRequestHandler delegate; public RetryableAuthorizationCodeGrantHandler(ReactiveOAuth2AuthorizationCodeGrantRequestHandler delegate) { this.delegate = delegate; } @Override public Mono<OAuth2AccessToken> handle(OAuth2AuthorizationCodeGrantRequest grantRequest) { return this.delegate.handle(grantRequest) .retryWhen(Retry.backoff(3, Duration.ofSeconds(1)) .filter(throwable -> throwable instanceof IOException || throwable instanceof IllegalStateException)); } }
然后在配置类中注册该处理器:
@Bean public ReactiveOAuth2AuthorizationCodeGrantRequestHandler retryableGrantHandler( ReactiveOAuth2AuthorizationCodeGrantRequestHandler defaultHandler) { return new RetryableAuthorizationCodeGrantHandler(defaultHandler); }
关键注意事项
- 限制重试次数和间隔,避免给身份提供商(IDP)造成不必要的压力
- 仅针对可恢复异常重试,如连接超时、读取超时、5xx服务器错误,不要重试无效授权码等客户端错误
- 若只需针对OAuth2客户端请求设置超时,优先选择自定义
WebClient的方式,避免全局配置影响其他请求
内容的提问来源于stack exchange,提问作者Poklakni
相关产品推荐
相关产品推荐

