给定以下代码,是否可以在应用程序运行程序中调用受客户端凭据保护的API?
@Bean public ApplicationRunner test( WebClient.Builder builder, ClientRegistrationRepository clientRegistrationRepo, OAuth2AuthorizedClientRepository authorizedClient) { return args -> { try { var oauth2 = new ServletOAuth2AuthorizedClientExchangeFilterFunction( clientRegistrationRepo, authorizedClient); oauth2.setDefaultClientRegistrationId("test"); var response = builder .apply(oauth2.oauth2Configuration()) .build() .get() .uri("test") .retrieve() .bodyToMono(String.class) .block(); log.info("Response - {}", response); } catch (Exception e) { log.error("Failed to call test.", e); } }; }
该代码由于以下原因而失败:
java.lang.IllegalArgumentException: request cannot be null
全栈,
java.lang.IllegalArgumentException: request cannot be null at org.springframework.util.Assert.notNull(Assert.java:198) ~[spring-core-5.1.5.RELEASE.jar:5.1.5.RELEASE] at org.springframework.security.oauth2.client.web.HttpSessionOAuth2AuthorizedClientRepository.loadAuthorizedClient(HttpSessionOAuth2AuthorizedClientRepository.java:47) ~[spring-security-oauth2-client-5.1.4.RELEASE.jar:5.1.4.RELEASE] at org.springframework.security.oauth2.client.web.reactive.function.client.ServletOAuth2AuthorizedClientExchangeFilterFunction.populateDefaultOAuth2AuthorizedClient(ServletOAuth2AuthorizedClientExchangeFilterFunction.java:364) ~[spring-security-oauth2-client-5.1.4.RELEASE.jar:5.1.4.RELEASE] at org.springframework.security.oauth2.client.web.reactive.function.client.ServletOAuth2AuthorizedClientExchangeFilterFunction.lambda$null$2(ServletOAuth2AuthorizedClientExchangeFilterFunction.java:209) ~[spring-security-oauth2-client-5.1.4.RELEASE.jar:5.1.4.RELEASE] at org.springframework.web.reactive.function.client.DefaultWebClient$DefaultRequestBodyUriSpec.attributes(DefaultWebClient.java:234) ~[spring-webflux-5.1.5.RELEASE.jar:5.1.5.RELEASE] at org.springframework.web.reactive.function.client.DefaultWebClient$DefaultRequestBodyUriSpec.attributes(DefaultWebClient.java:153) ~[spring-webflux-5.1.5.RELEASE.jar:5.1.5.RELEASE]
失败的方法看起来像
public <T extends OAuth2AuthorizedClient> T loadAuthorizedClient( String clientRegistrationId, Authentication principal, HttpServletRequest request){ Assert.hasText(clientRegistrationId, "clientRegistrationId cannot be empty"); Assert.notNull(request, "request cannot be null"); return (OAuth2AuthorizedClient)this .getAuthorizedClients(request) .get(clientRegistrationId); }
这是有道理的,因为它不需要HttpServletRequest使用,它在应用程序启动时被调用。
HttpServletRequest
除了我自己禁止操作外,还有其他解决方法OAuth2AuthorizedClientRepository吗?
OAuth2AuthorizedClientRepository
//编辑,
这不是完全反应堆。它是一个Spring Web堆栈,其中使用了WebClient。
我很清楚ServerOAuth2AuthorizedClientExchangeFilterFunction哪个适用于完全响应式堆栈,ReactiveClientRegistrationRepository而ReactiveOauth2AuthorizedClient哪些要求不适用,由于基于Servlet堆栈而不是响应式的应用程序中的要求,它们不可用。
ServerOAuth2AuthorizedClientExchangeFilterFunction
ReactiveClientRegistrationRepository
ReactiveOauth2AuthorizedClient
由于我也偶然发现了这个问题,因此我将详细介绍DarrenForsythe的最新答案,以使其他人更容易找到:
OP提交的问题导致该问题的实施OAuth2AuthorizedClientManager能够
OAuth2AuthorizedClientManager
在HttpServletRequest上下文之外运行,例如在计划的/后台线程中和/或在服务层中
(来自官方文档)
所述实现AuthorizedClientServiceOAuth2AuthorizedClientManager传递给,ServletOAuth2AuthorizedClientExchangeFilterFunction以替换默认的实现。
AuthorizedClientServiceOAuth2AuthorizedClientManager
ServletOAuth2AuthorizedClientExchangeFilterFunction
在我的示例中,这看起来像这样:
@Bean public OAuth2AuthorizedClientManager authorizedClientManager( ClientRegistrationRepository clientRegistrationRepository, OAuth2AuthorizedClientService clientService) { OAuth2AuthorizedClientProvider authorizedClientProvider = OAuth2AuthorizedClientProviderBuilder.builder() .clientCredentials() .build(); AuthorizedClientServiceOAuth2AuthorizedClientManager authorizedClientManager = new AuthorizedClientServiceOAuth2AuthorizedClientManager( clientRegistrationRepository, clientService); authorizedClientManager.setAuthorizedClientProvider(authorizedClientProvider); return authorizedClientManager; } @Bean WebClient webClient(OAuth2AuthorizedClientManager authorizedClientManager) { ServletOAuth2AuthorizedClientExchangeFilterFunction oauth2 = new ServletOAuth2AuthorizedClientExchangeFilterFunction( authorizedClientManager); oauth2.setDefaultClientRegistrationId("keycloak"); return WebClient.builder().apply(oauth2.oauth2Configuration()).build(); }