Spring boot Spring Boot反应式网络客户端“;serverWebExchange必须为空";当使用Spring Security OAuth时
我想使用Spring Boot WebFlux应用程序中的WebClient,该应用程序是使用Spring Security OAuth 2客户端凭据设置的 但是,我得到:Spring boot Spring Boot反应式网络客户端“;serverWebExchange必须为空";当使用Spring Security OAuth时,spring-boot,spring-security,spring-webflux,Spring Boot,Spring Security,Spring Webflux,我想使用Spring Boot WebFlux应用程序中的WebClient,该应用程序是使用Spring Security OAuth 2客户端凭据设置的 但是,我得到:java.lang.IllegalArgumentException:serverWebExchange必须为null 代码如下: 当我通过从pom.xml中删除它来禁用Spring安全性时,它可以正常工作 当我继续使用Spring安全性时,它不会将webClient()链结果返回给控制器并打印出来,而是同样有效 当使用Spr
java.lang.IllegalArgumentException:serverWebExchange必须为null
代码如下:
当我通过从pom.xml
中删除它来禁用Spring安全性时,它可以正常工作
当我继续使用Spring安全性时,它不会将webClient()
链结果返回给控制器并打印出来,而是同样有效
当使用Spring Security时,反应式客户端和服务器似乎无法协同工作。如何让它们一起运行?如果您使用
未经验证的服务器OAuth2AuthorizedClientRepository
,它会将webExchange从源请求传播到您的@RestController
到WebClient
,您正在使用它来调用导致错误的其他服务java.lang.IllegalArgumentException:serverWebExchange必须为null
要解决此问题,请使用服务器OAuth2AuthorizedClient存储库的自动连线实现(这恰好是AuthenticatedPrincipalServerOAuth2AuthorizedClient存储库
)
对我来说,问题就在后面
对以下链接的评论对我有用
https://www.gitmemory.com/issue/spring-projects/spring-security/8444/621567261
另一环节
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
}
@Bean
趣味服务器OAuth2AuthorizedClient ChangeFilterFunction(客户端注册:列表)
:ServerOAuth2AuthorizedClientExchangeFilterFunction{
val clientRegistrationRepository=InMemoryReactiveClientRegistrationRepository(clientRegistrations)
val authorizedClientService=InMemoryReactiveAuth2AuthorizedClientService(clientRegistrationRepository)
val OAuth2AuthorizedClient Manager=AuthorizedClient服务反应OAuth2AuthorizedClient Manager(
clientRegistrationRepository,
授权客户服务
)
val filterFunction=ServerOAuth2AuthorizedClientChangeFilterFunction(oAuth2AuthorizedClientManager)
filterFunction.setDefaultClientRegistrationId(clientId)
返回过滤器功能
}
您已经使用未经验证的回购/交换设置了webclient。本质上,它期望在反应式servlet上下文持有者上进行null或匿名身份验证。当它打电话时,谢谢@Darrenforsyth。你能建议我该怎么做吗?而不是:ServerOAuth2AuthorizedClientChangeFilterFunction oauth=new ServerOAuth2AuthorizedClientChangeFilterFunction(clientRegistrations,new Unauthenticated ServerOAuth2AuthorizedClientRepository());应该能够自动连线服务器OAuth2AuthorizedClientRepository
,在中,只有两个具体的impl可用。UnAuthenticated是另一个没有与itI关联的主体的请求,我有完全相同的问题。当我通过单元测试调用受oauth2客户端凭据保护的资源时,一切正常。但是,当我通过未经验证的rest请求调用它时,它似乎传播了反应式servlet上下文持有者,而不是创建一个新的。您的“实际代码”无法编译。
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
}