Spring 当 Spring 安全 OAuth 正在使用时 "serverWebExchange must be null" 启动 Reactive WebClient
Spring Boot Reactive WebClient "serverWebExchange must be null" when Spring Security OAuth is in use
我想使用 Spring Boot WebFlux 应用程序中的 WebClient,该应用程序使用 Spring Security OAuth 2 Client Credentials 设置。
但是,我得到:java.lang.IllegalArgumentException: serverWebExchange must be null
代码在这里:https://github.com/mparaz/spring-apigee-client
当我通过从 pom.xml
中删除它来禁用 Spring 安全性时,它可以正常工作。
当我继续使用 Spring 安全性,但不是将 webClient()
链结果返回给控制器,而是将其打印出来时,它也有效。
使用 Spring 安全性时,Reactive 客户端和服务器似乎无法协同工作。我怎样才能让他们 运行 在一起?
似乎如果您使用 UnAuthenticatedServerOAuth2AuthorizedClientRepository
它会将 webExchange 从源请求传播到您的 @RestController
到您用来调用其他服务的 WebClient
导致 java.lang.IllegalArgumentException: serverWebExchange must be null
要解决此问题,请使用 ServerOAuth2AuthorizedClientRepository
的自动装配实现(恰好是 AuthenticatedPrincipalServerOAuth2AuthorizedClientRepository
)
@Bean
@LoadBalanced
public WebClient.Builder loadBalancedWebClientBuilder(ReactiveClientRegistrationRepository clientRegistrations,
ObjectMapper objectMapper,
ServerOAuth2AuthorizedClientRepository clientRepository) {
ServerOAuth2AuthorizedClientExchangeFilterFunction oauth2ClientFilter = new ServerOAuth2AuthorizedClientExchangeFilterFunction(
clientRegistrations,
clientRepository);
oauth2ClientFilter.setDefaultClientRegistrationId("apigee");
WebClient.Builder builder = WebClient.builder();
builder.defaultHeader("Content-Type", MediaType.APPLICATION_JSON.toString());
builder.defaultHeader("Accept", MediaType.APPLICATION_JSON.toString());
builder.filter(oauth2ClientFilter);
return builder;
}
对我来说问题如下
The DefaultOAuth2AuthorizedClientManager is designed to be used within the context of a HttpServletRequest. When operating outside of a HttpServletRequest context, use AuthorizedClientServiceOAuth2AuthorizedClientManager instead.
对以下内容的评论 link 对我有用
https://www.gitmemory.com/issue/spring-projects/spring-security/8444/621567261
另一个link
https://github.com/spring-projects/spring-security/issues/8230
评论
DefaultReactiveOAuth2AuthorizedClientManager is intended to be used within a request context.
Given that you're seeing serverWebExchange cannot be null, you must be operating outside of a request context, which in case you should use AuthorizedClientServiceReactiveOAuth2AuthorizedClientManager instead.
NOTE: Change the ServerOAuth2AuthorizedClientRepository parameter to ReactiveOAuth2AuthorizedClientService.
实际代码
@Bean
fun serverOAuth2AuthorizedClientExchangeFilterFunction(clientRegistrations: List<ClientRegistration>)
: ServerOAuth2AuthorizedClientExchangeFilterFunction {
val clientRegistrationRepository = InMemoryReactiveClientRegistrationRepository(clientRegistrations)
val authorizedClientService = InMemoryReactiveOAuth2AuthorizedClientService(clientRegistrationRepository)
val oAuth2AuthorizedClientManager = AuthorizedClientServiceReactiveOAuth2AuthorizedClientManager(
clientRegistrationRepository,
authorizedClientService
)
val filterFunction = ServerOAuth2AuthorizedClientExchangeFilterFunction(oAuth2AuthorizedClientManager)
filterFunction.setDefaultClientRegistrationId(clientId)
return filterFunction
}
我想使用 Spring Boot WebFlux 应用程序中的 WebClient,该应用程序使用 Spring Security OAuth 2 Client Credentials 设置。
但是,我得到:java.lang.IllegalArgumentException: serverWebExchange must be null
代码在这里:https://github.com/mparaz/spring-apigee-client
当我通过从 pom.xml
中删除它来禁用 Spring 安全性时,它可以正常工作。
当我继续使用 Spring 安全性,但不是将 webClient()
链结果返回给控制器,而是将其打印出来时,它也有效。
使用 Spring 安全性时,Reactive 客户端和服务器似乎无法协同工作。我怎样才能让他们 运行 在一起?
似乎如果您使用 UnAuthenticatedServerOAuth2AuthorizedClientRepository
它会将 webExchange 从源请求传播到您的 @RestController
到您用来调用其他服务的 WebClient
导致 java.lang.IllegalArgumentException: serverWebExchange must be null
要解决此问题,请使用 ServerOAuth2AuthorizedClientRepository
的自动装配实现(恰好是 AuthenticatedPrincipalServerOAuth2AuthorizedClientRepository
)
@Bean
@LoadBalanced
public WebClient.Builder loadBalancedWebClientBuilder(ReactiveClientRegistrationRepository clientRegistrations,
ObjectMapper objectMapper,
ServerOAuth2AuthorizedClientRepository clientRepository) {
ServerOAuth2AuthorizedClientExchangeFilterFunction oauth2ClientFilter = new ServerOAuth2AuthorizedClientExchangeFilterFunction(
clientRegistrations,
clientRepository);
oauth2ClientFilter.setDefaultClientRegistrationId("apigee");
WebClient.Builder builder = WebClient.builder();
builder.defaultHeader("Content-Type", MediaType.APPLICATION_JSON.toString());
builder.defaultHeader("Accept", MediaType.APPLICATION_JSON.toString());
builder.filter(oauth2ClientFilter);
return builder;
}
对我来说问题如下
The DefaultOAuth2AuthorizedClientManager is designed to be used within the context of a HttpServletRequest. When operating outside of a HttpServletRequest context, use AuthorizedClientServiceOAuth2AuthorizedClientManager instead.
对以下内容的评论 link 对我有用
https://www.gitmemory.com/issue/spring-projects/spring-security/8444/621567261
另一个link
https://github.com/spring-projects/spring-security/issues/8230
评论
DefaultReactiveOAuth2AuthorizedClientManager is intended to be used within a request context.
Given that you're seeing serverWebExchange cannot be null, you must be operating outside of a request context, which in case you should use AuthorizedClientServiceReactiveOAuth2AuthorizedClientManager instead.
NOTE: Change the ServerOAuth2AuthorizedClientRepository parameter to ReactiveOAuth2AuthorizedClientService.
实际代码
@Bean
fun serverOAuth2AuthorizedClientExchangeFilterFunction(clientRegistrations: List<ClientRegistration>)
: ServerOAuth2AuthorizedClientExchangeFilterFunction {
val clientRegistrationRepository = InMemoryReactiveClientRegistrationRepository(clientRegistrations)
val authorizedClientService = InMemoryReactiveOAuth2AuthorizedClientService(clientRegistrationRepository)
val oAuth2AuthorizedClientManager = AuthorizedClientServiceReactiveOAuth2AuthorizedClientManager(
clientRegistrationRepository,
authorizedClientService
)
val filterFunction = ServerOAuth2AuthorizedClientExchangeFilterFunction(oAuth2AuthorizedClientManager)
filterFunction.setDefaultClientRegistrationId(clientId)
return filterFunction
}