gpt4 book ai didi

spring-boot - `servletRequest cannot be null` -> SpringBoot - WebClient - 使用 Keycloak 获取请求

转载 作者:行者123 更新时间:2023-12-02 18:39:40 26 4
gpt4 key购买 nike

我正在尝试在两个微服务之间发出 GET 请求(使用 Keycloak 身份验证)。

假设微服务 A 向微服务 B 请求一些资源。微服务 B 有一个 GET 端点,它似乎可以正常工作,因为在从 postman 或 intelliJ http_client 发出请求时我可以看到正确的响应。

在微服务 A 中,我正在尝试发出请求(我确实尝试发出阻塞和非阻塞请求):

  • 阻止请求
String response = webClient.mutate()
.baseUrl(this.serverUri)
.build().get()
.uri(uriBuilder -> uriBuilder
.path("/users/tokens/{id}")
.build(userId))
.header(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE)
.attributes(ServerOAuth2AuthorizedClientExchangeFilterFunction
.clientRegistrationId("keycloak"))
.retrieve()
.bodyToMono(String.class)
.doOnError(RuntimeException::new)
.block();
  • 非阻塞请求:
        webClient.mutate()
.baseUrl(this.serverUri)
.build().get()
.uri(uriBuilder -> uriBuilder
.path("/users/tokens/{id}")
.build(userId))
.header(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE)
.attributes(ServerOAuth2AuthorizedClientExchangeFilterFunction
.clientRegistrationId("keycloak"))
.retrieve()
.bodyToMono(String.class)
.subscribe(resp -> {
JSONObject jsonObject = new JSONObject(resp);
JSONArray jsonArray = jsonObject.getJSONArray("Tokens");
for (int i = 0; i < jsonArray.length(); i++) {
log.info("token :: " + jsonArray.get(i).toString());
}
});

这是我的 WebClient 配置:

@Configuration
public class WebClientConfiguration {

@Bean
public OAuth2AuthorizedClientManager authorizedClientManager(
ClientRegistrationRepository clientRegistrationRepository,
OAuth2AuthorizedClientRepository authorizedClientRepository) {

OAuth2AuthorizedClientProvider authorizedClientProvider =
OAuth2AuthorizedClientProviderBuilder.builder()
.refreshToken()
.clientCredentials()
.build();

DefaultOAuth2AuthorizedClientManager authorizedClientManager =
new DefaultOAuth2AuthorizedClientManager(
clientRegistrationRepository, authorizedClientRepository);
authorizedClientManager.setAuthorizedClientProvider(authorizedClientProvider);

return authorizedClientManager;
}

@Bean
WebClient webClient(OAuth2AuthorizedClientManager authorizedClientManager) {
ServletOAuth2AuthorizedClientExchangeFilterFunction oauth2Client =
new ServletOAuth2AuthorizedClientExchangeFilterFunction(authorizedClientManager);
return WebClient.builder()
.apply(oauth2Client.oauth2Configuration())
.build();
}
}

我所做的一切都以这种错误结束:

2021-06-29 16:44:07.854 ERROR 390692 --- [oundedElastic-1] reactor.core.publisher.Operators         : Operator called default onErrorDropped

reactor.core.Exceptions$ErrorCallbackNotImplemented: java.lang.IllegalArgumentException: servletRequest cannot be null
Caused by: java.lang.IllegalArgumentException: servletRequest cannot be null
at org.springframework.util.Assert.notNull(Assert.java:201) ~[spring-core-5.3.5.jar:5.3.5]
Suppressed: reactor.core.publisher.FluxOnAssembly$OnAssemblyException:
Error has been observed at the following site(s):
|_ checkpoint ⇢ Request to GET https://localhost:8080/api/users/tokens/94a2d4f7-b372-4e13-aa16-7b244c099721 [DefaultWebClient]
Stack trace:
at org.springframework.util.Assert.notNull(Assert.java:201) ~[spring-core-5.3.5.jar:5.3.5]
at org.springframework.security.oauth2.client.web.DefaultOAuth2AuthorizedClientManager.authorize(DefaultOAuth2AuthorizedClientManager.java:144) ~[spring-security-oauth2-client-5.4.5.jar:5.4.5]
at org.springframework.security.oauth2.client.web.reactive.function.client.ServletOAuth2AuthorizedClientExchangeFilterFunction.lambda$authorizeClient$24(ServletOAuth2AuthorizedClientExchangeFilterFunction.java:552) ~[spring-security-oauth2-client-5.4.5.jar:5.4.5]
at reactor.core.publisher.MonoSupplier.call(MonoSupplier.java:85) ~[reactor-core-3.4.4.jar:3.4.4]
at reactor.core.publisher.FluxSubscribeOnCallable$CallableSubscribeOnSubscription.run(FluxSubscribeOnCallable.java:227) ~[reactor-core-3.4.4.jar:3.4.4]
at reactor.core.scheduler.SchedulerTask.call(SchedulerTask.java:68) [reactor-core-3.4.4.jar:3.4.4]
at reactor.core.scheduler.SchedulerTask.call(SchedulerTask.java:28) [reactor-core-3.4.4.jar:3.4.4]

我是不是漏了什么?

[编辑]

按照此处的建议更改 WebClientConfiguration ( Spring Security 5 Calling OAuth2 Secured API in Application Runner results in IllegalArgumentException ) 达到了目的:

    @Bean
public OAuth2AuthorizedClientManager authorizedClientManager(
ClientRegistrationRepository clientRegistrationRepository,
OAuth2AuthorizedClientService clientService) {

OAuth2AuthorizedClientProvider authorizedClientProvider =
OAuth2AuthorizedClientProviderBuilder.builder()
.refreshToken()
.clientCredentials()
.build();

AuthorizedClientServiceOAuth2AuthorizedClientManager authorizedClientManager =
new AuthorizedClientServiceOAuth2AuthorizedClientManager(clientRegistrationRepository, clientService);

authorizedClientManager.setAuthorizedClientProvider(authorizedClientProvider);

return authorizedClientManager;
}

@Bean
WebClient webClient(OAuth2AuthorizedClientManager authorizedClientManager) {
ServletOAuth2AuthorizedClientExchangeFilterFunction oauth2Client =
new ServletOAuth2AuthorizedClientExchangeFilterFunction(authorizedClientManager);
return WebClient.builder()
.apply(oauth2Client.oauth2Configuration())
.build();
}

谁能解释一下为什么?

最佳答案

我不确定您在什么上下文中运行它。但是错误消息表明请求不是在 HttpServletRequest 的上下文中启动的。如果您的请求是由调度程序或类似的东西启动的,那么就没有 servletRequest。

Spring 文档说对于这种情况,您需要 AuthorizedClientServiceOAuth2AuthorizedClientManager 实现。

DefaultOAuth2AuthorizedClientManager [...] The default implementationof an OAuth2AuthorizedClientManager for use within the context of a HttpServletRequest.(When operating outside of the context of a HttpServletRequest, use AuthorizedClientServiceOAuth2AuthorizedClientManager instead.)

from the official docs

AuthorizedClientServiceOAuth2AuthorizedClientManager [...] An implementation of an OAuth2AuthorizedClientManager that is capable of operating outside of the context of a HttpServletRequest, e.g. in a scheduled/background thread and/or in the service-tier.(When operating within the context of a HttpServletRequest, use DefaultOAuth2AuthorizedClientManager instead.)

from the official docs

关于spring-boot - `servletRequest cannot be null` -> SpringBoot - WebClient - 使用 Keycloak 获取请求,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/68181151/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com