问题描述
我正在尝试在两个微服务之间发出 GET 请求(使用 Keycloak 身份验证)。
假设微服务 A 向微服务 B 请求一些资源。 微服务 B 有一个 GET 端点,它似乎可以工作,因为在从邮递员或 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]
我是不是遗漏了什么?
[编辑]
按照此处的建议 (Spring Security 5 Calling OAuth2 Secured API in Application Runner results in IllegalArgumentException) 更改 WebClientConfiguration 可以解决问题:
@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();
}
有人能解释一下原因吗?
解决方法
暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!
如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。
小编邮箱:dio#foxmail.com (将#修改为@)