Spring Boot Webflux OAuth2客户端凭证流对接Azure AD异常求助
Spring Boot 2.6.5 Webflux OAuth2 Client Credentials对接Azure AD问题解决思路
一、依赖版本校验(pom.xml)
确保核心依赖版本与Spring Boot 2.6.5匹配,避免依赖冲突:
<dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-webflux</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-oauth2-client</artifactId> </dependency> <dependency> <groupId>org.springframework.security</groupId> <artifactId>spring-security-oauth2-jose</artifactId> </dependency> </dependencies>
二、解决启动时缺失ReactiveOAuth2AuthorizedClientManager Bean的问题
Spring Boot自动配置在标准场景下会生成该Bean,若未生成,需手动配置正确的授权管理器实例,核心是指定Client Credentials模式的授权提供者:
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.security.oauth2.client.ReactiveOAuth2AuthorizedClientManager; import org.springframework.security.oauth2.client.ReactiveOAuth2AuthorizedClientProvider; import org.springframework.security.oauth2.client.ReactiveOAuth2AuthorizedClientProviderBuilder; import org.springframework.security.oauth2.client.registration.ReactiveClientRegistrationRepository; import org.springframework.security.oauth2.client.web.DefaultReactiveOAuth2AuthorizedClientManager; import org.springframework.security.oauth2.client.web.server.ServerOAuth2AuthorizedClientRepository; import org.springframework.security.oauth2.client.web.server.ServerOAuth2AuthorizedClientExchangeFilterFunction; import org.springframework.web.reactive.function.client.WebClient; @Configuration public class CommonConfig { @Bean public ReactiveOAuth2AuthorizedClientManager reactiveOAuth2AuthorizedClientManager( ReactiveClientRegistrationRepository clientRegistrationRepository, ServerOAuth2AuthorizedClientRepository authorizedClientRepository) { ReactiveOAuth2AuthorizedClientProvider authorizedClientProvider = ReactiveOAuth2AuthorizedClientProviderBuilder.builder() .clientCredentials() // 明确指定Client Credentials模式 .build(); DefaultReactiveOAuth2AuthorizedClientManager authorizedClientManager = new DefaultReactiveOAuth2AuthorizedClientManager( clientRegistrationRepository, authorizedClientRepository); authorizedClientManager.setAuthorizedClientProvider(authorizedClientProvider); return authorizedClientManager; } }
三、解决serverWebExchange cannot be null异常
该异常核心原因是Webflux环境错误使用了Servlet生态的OAuth2过滤器,需替换为Webflux专属的ServerOAuth2AuthorizedClientExchangeFilterFunction,修正WebClient配置:
@Bean public WebClient webClient(ReactiveOAuth2AuthorizedClientManager authorizedClientManager) { ServerOAuth2AuthorizedClientExchangeFilterFunction oauth2Filter = new ServerOAuth2AuthorizedClientExchangeFilterFunction(authorizedClientManager); oauth2Filter.setDefaultClientRegistrationId("azure-ad"); // 对应配置文件中的客户端ID return WebClient.builder() .filter(oauth2Filter) .build(); }
四、application.yaml配置规范
确保Azure AD客户端信息配置准确,符合Client Credentials模式要求:
spring: security: oauth2: client: registration: azure-ad: client-id: <你的Azure AD客户端ID> client-secret: <你的客户端密钥> authorization-grant-type: client_credentials scope: api://<目标API资源ID>/.default # Azure AD专属格式 provider: azure-ad: token-uri: https://login.microsoftonline.com/<你的租户ID>/oauth2/v2.0/token
五、受保护接口调用示例
Web上下文内调用(如Controller)
import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RestController; import org.springframework.web.reactive.function.client.WebClient; import reactor.core.publisher.Mono; @RestController public class ApiCallController { private final WebClient webClient; public ApiCallController(WebClient webClient) { this.webClient = webClient; } @GetMapping("/invoke-protected-api") public Mono<String> invokeProtectedApi() { return webClient.get() .uri("https://<受保护API地址>") .retrieve() .bodyToMono(String.class); } }
非Web上下文调用(如定时任务)
若在无ServerWebExchange的场景调用,需手动获取令牌:
import org.springframework.security.oauth2.client.ReactiveOAuth2AuthorizedClientManager; import org.springframework.security.oauth2.client.OAuth2AuthorizeRequest; import reactor.core.publisher.Mono; public class ScheduledTask { private final ReactiveOAuth2AuthorizedClientManager authorizedClientManager; public void executeTask() { OAuth2AuthorizeRequest authorizeRequest = OAuth2AuthorizeRequest.withClientRegistrationId("azure-ad") .principal("client-credentials-principal") // Client Credentials模式可自定义标识 .build(); authorizedClientManager.authorize(authorizeRequest) .flatMap(client -> { String token = client.getAccessToken().getTokenValue(); return WebClient.create() .get() .uri("https://<受保护API地址>") .header("Authorization", "Bearer " + token) .retrieve() .bodyToMono(String.class); }) .subscribe(result -> { // 处理返回结果 }); } }
内容的提问来源于stack exchange,提问作者Venu
相关产品推荐
相关产品推荐

