英文:
A connection attempt failed because the connected party did not properly respond after a period of time - spring security, webclient
问题
Here is the translated code portion:
我有一个Java Spring服务,我正在将RestTemplate迁移到WebClient,并且发现了代理的问题(这是我的猜测)。
整个配置在我以前的问题下已经描述在这里:https://stackoverflow.com/questions/76287935/add-additional-parameter-to-the-spring-security-oauth-token-request 但我会在这里再次粘贴:
项目详情:
spring-boot- 3.0.X
这是customclient获取令牌所需的请求:
URI:xxxxxxx/token
```json
{
"grant_type": "client_credentials",
"client_id": "xxxx",
"client_secret": "xxxxxxxx",
"account_id": "123456789"
}
application.yml
security:
oauth2:
client:
registration:
custom-client:
provider: custom-client
client-id: xxxxxxxxxxxxxxx
client-secret: xxxxxxxxxxxxxxx
authorization-grant-type: client_credentials
client-authentication-method: post
provider:
custom-client:
token-uri: xxxxxxxxxxxxxxxxxxxxxxxxxx/token
WebClientConfig.java
@Configuration
@Getter
@Setter
public class WebClientConfig {
@Bean
public OAuth2AuthorizedClientManager webclientManager(ClientRegistrationRepository clientRegistrationRepository,
OAuth2AuthorizedClientService authorizedClientService) {
OAuth2AuthorizedClientProvider authorizedClientProvider = OAuth2AuthorizedClientProviderBuilder.builder()
.clientCredentials()
.build();
AuthorizedClientServiceOAuth2AuthorizedClientManager authorizedClientManager =
new AuthorizedClientServiceOAuth2AuthorizedClientManager(clientRegistrationRepository, authorizedClientService);
authorizedClientManager.setAuthorizedClientProvider(authorizedClientProvider);
return authorizedClientManager;
}
@Bean
public WebClient customWebClient(@Qualifier("webclientManager") OAuth2AuthorizedClientManager authorizedClientManager) {
ServletOAuth2AuthorizedClientExchangeFilterFunction oAuth2Filer = new ServletOAuth2AuthorizedClientExchangeFilterFunction(authorizedClientManager);
oAuth2Filer.setDefaultClientRegistrationId("customclient");
return WebClient.builder()
.filter(oAuth2Filer)
.baseUrl(apiUrl)
.build();
}
}
这是一个我想要使用WebClient进行一些REST调用的示例服务:
MyService.java
@Service
public class MyService{
WebClient webClient;
public MyService(@Qualifier("customClient") WebClient webClient) {
this.webClient = webClient;
}
public String testRequest() {
return webClient.get()
.uri("xxxxxx")
.retrieve()
.bodyToMono(String.class)
.block();
}
}
当我尝试测试我的代码并使用WebClient向其他系统发出一些REST调用时,我收到以下响应:
>
> "[invalid_token_response] 尝试检索OAuth 2.0访问令牌响应时发生错误:在对“https:/xxxxxxxxxxxxxx/oauth2/token”的POST请求上发生I/O错误:连接尝试失败,因为连接方在一段时间后未能正确响应,或者建立的连接失败,因为连接的主机未能正确响应;嵌套异常是java.net.SocketException:连接尝试失败,因为连接方在一段时间后未能正确响应,或者建立的连接失败,因为连接的主机未能正确响应"
我认为这可能是代理的问题,我已经尝试添加类似以下内容:
@Configuration
@Getter
@Setter
public class WebClientConfig {
@Bean
public OAuth2AuthorizedClientManager webclientManager(ClientRegistrationRepository clientRegistrationRepository,
OAuth2AuthorizedClientService authorizedClientService) {
OAuth2AuthorizedClientProvider authorizedClientProvider = OAuth2AuthorizedClientProviderBuilder.builder()
.clientCredentials()
.build();
AuthorizedClientServiceOAuth2AuthorizedClientManager authorizedClientManager =
new AuthorizedClientServiceOAuth2AuthorizedClientManager(clientRegistrationRepository, authorizedClientService);
authorizedClientManager.setAuthorizedClientProvider(authorizedClientProvider);
return authorizedClientManager;
}
@Bean
public WebClient customWebClient(@Qualifier("webclientManager") OAuth2AuthorizedClientManager authorizedClientManager,
final @Value("${proxy.url}" String proxyUrl,
final @Value("${proxy.port}" String proxyPort,
final @Value("${proxy.username}" String proxyUsername,
final @Value("${proxy.password}" String proxyPassword) {
ServletOAuth2AuthorizedClientExchangeFilterFunction oAuth2Filer = new ServletOAuth2AuthorizedClientExchangeFilterFunction(authorizedClientManager);
oAuth2Filer.setDefaultClientRegistrationId("customclient");
Function<String, String> httpsProxyPassword = username -> proxyPassword;
HttpClient client = HttpClient.create()
.proxy(proxy -> proxy.type(ProxyProvider.Proxy.HTTP)
.host(proxyUrl)
.port(proxyPort)
.password(httpsProxyPassword)
.username(proxyUsername));
return WebClient.builder()
.clientConnector(new ReactorClientHttpConnector(client))
.filter(oAuth2Filer)
.baseUrl(apiUrl)
.build();
}
}
但响应仍然相同。
<details>
<summary>英文:</summary>
I have a Java Spring service and I'm migrating a RestTemplate to a WebClient and spotted a problem with proxy (that's my guess).
Whole configuration is described here under my previous question here: https://stackoverflow.com/questions/76287935/add-additional-parameter-to-the-spring-security-oauth-token-request but I will copy paste it here again:
Project details:
spring-boot- 3.0.X
This is request required by customclient to get the token:
uri: xxxxxxx/token
{
"grant_type": "client_credentials",
"client_id": "xxxx",
"client_secret": "xxxxxxxx",
"account_id": "123456789"
}
application.yml
security:
oauth2:
client:
registration:
custom-client:
provider: custom-client
client-id: xxxxxxxxxxxxxxx
client-secret: xxxxxxxxxxxxxxx
authorization-grant-type: client_credentials
client-authentication-method: post
provider:
custom-client:
token-uri: xxxxxxxxxxxxxxxxxxxxxxxxxx/token
WebClientConfig.java
@Configuration
@Getter
@Setter
public class WebClientConfig {
@Bean
public OAuth2AuthorizedClientManager webclientManager(ClientRegistrationRepository clientRegistrationRepository,
OAuth2AuthorizedClientService authorizedClientService) {
OAuth2AuthorizedClientProvider authorizedClientProvider = OAuth2AuthorizedClientProviderBuilder.builder()
.clientCredentials()
.build();
AuthorizedClientServiceOAuth2AuthorizedClientManager authorizedClientManager =
new AuthorizedClientServiceOAuth2AuthorizedClientManager(clientRegistrationRepository, authorizedClientService);
authorizedClientManager.setAuthorizedClientProvider(authorizedClientProvider);
return authorizedClientManager;
}
@Bean
public WebClient customWebClient(@Qualifier("webclientManager") OAuth2AuthorizedClientManager authorizedClientManager) {
ServletOAuth2AuthorizedClientExchangeFilterFunction oAuth2Filer = new ServletOAuth2AuthorizedClientExchangeFilterFunction(authorizedClientManager);
oAuth2Filer.setDefaultClientRegistrationId("customclient");
return WebClient.builder()
.filter(oAuth2Filer)
.baseUrl(apiUrl)
.build();
}
}
This is an example service where I would like to use webClient to make some REST call:
MyService.java
@Service
public class MyService{
WebClient webClient;
public MyService(@Qualifier("customClient") WebClient webClient) {
this.webClient = webClient;
}
public String testRequest() {
return webClient.get()
.uri("xxxxxx")
.retrieve()
.bodyToMono(String.class)
.block();
}
}
When I'm trying to test my code and make some REST call to other system using WebClient, I'm receiving following response:
>
> "\[invalid_token_response\] An error occurred while attempting to retrieve the OAuth 2.0 Access Token Response: I/O error on POST request for "https:/xxxxxxxxxxxxxx/oauth2/token": A connection attempt failed because the connected party did not properly respond after a period of time, or established connection failed because connected host has failed to respond; nested exception is java.net.SocketException: A connection attempt failed because the connected party did not properly respond after a period of time, or established connection failed because connected host has failed to respond"
I think it can be a problem with proxy and I've tried add something like this:
@Configuration
@Getter
@Setter
public class WebClientConfig {
@Bean
public OAuth2AuthorizedClientManager webclientManager(ClientRegistrationRepository clientRegistrationRepository,
OAuth2AuthorizedClientService authorizedClientService) {
OAuth2AuthorizedClientProvider authorizedClientProvider = OAuth2AuthorizedClientProviderBuilder.builder()
.clientCredentials()
.build();
AuthorizedClientServiceOAuth2AuthorizedClientManager authorizedClientManager =
new AuthorizedClientServiceOAuth2AuthorizedClientManager(clientRegistrationRepository, authorizedClientService);
authorizedClientManager.setAuthorizedClientProvider(authorizedClientProvider);
return authorizedClientManager;
}
@Bean
public WebClient customWebClient(@Qualifier("webclientManager") OAuth2AuthorizedClientManager authorizedClientManager,
final @Value("${proxy.url}" String proxyUrl,
final @Value("${proxy.port}" String proxyPort,
final @Value("${proxy.username}" String proxyUsername,
final @Value("${proxy.password}" String proxyPassword) {
ServletOAuth2AuthorizedClientExchangeFilterFunction oAuth2Filer = new ServletOAuth2AuthorizedClientExchangeFilterFunction(authorizedClientManager);
oAuth2Filer.setDefaultClientRegistrationId("customclient");
Function<String, String> httpsProxyPassword = username -> proxyPassword;
HttpClient client = HttpClient.create()
.proxy(proxy -> proxy.type(ProxyProvider.Proxy.HTTP)
.host(proxyUrl)
.port(proxyPort)
.password(httpsProxyPassword)
.username(proxyUsername));
return WebClient.builder()
.clientConnector(new ReactorClientHttpConnector(client))
.filter(oAuth2Filer)
.baseUrl(apiUrl)
.build();
}
}
But the repsonse is still the same.
</details>
# 答案1
**得分**: 0
在花费了几个小时进行调试并尝试了多种方法之后,最终发现问题出在令牌请求本身,它必须单独配置代理(除了在`.clientConnector()`中完成的资源代理配置之外)。
示例链接:
https://stackoverflow.com/questions/59147147/webclient-proxy-configuration-not-working-with-oauth2/65790535#65790535
https://blog.doubleslash.de/spring-oauth2-client-authorization-request-proxy-support
<details>
<summary>英文:</summary>
After spending few hours debugging and trying multiple way, It turned out to be a problem with token request itself, which has to have proxy configured separately (in addition to the resource proxy config done within .clientConnector()) .
Examples here:
https://stackoverflow.com/questions/59147147/webclient-proxy-configuration-not-working-with-oauth2/65790535#65790535
https://blog.doubleslash.de/spring-oauth2-client-authorization-request-proxy-support
</details>
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论