A connection attempt failed because the connected party did not properly respond after a period of time – spring security, webclient

huangapple go评论67阅读模式
英文:

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获取令牌所需的请求

URIxxxxxxx/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&#39;m migrating a RestTemplate to a WebClient and spotted a problem with proxy (that&#39;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(&quot;webclientManager&quot;) OAuth2AuthorizedClientManager authorizedClientManager) {
ServletOAuth2AuthorizedClientExchangeFilterFunction oAuth2Filer = new ServletOAuth2AuthorizedClientExchangeFilterFunction(authorizedClientManager);
oAuth2Filer.setDefaultClientRegistrationId(&quot;customclient&quot;);
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(&quot;customClient&quot;) WebClient webClient) {
this.webClient = webClient;
}
public String testRequest() {
return webClient.get()
.uri(&quot;xxxxxx&quot;)
.retrieve()
.bodyToMono(String.class)
.block();
}

}


When I&#39;m trying to test my code and make some REST call to other system using WebClient, I&#39;m receiving following response:
&gt;   
&gt; &quot;\[invalid_token_response\] An error occurred while attempting to retrieve the OAuth 2.0 Access Token Response: I/O error on POST request for &quot;https:/xxxxxxxxxxxxxx/oauth2/token&quot;: 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&quot;
I think it can be a problem with proxy and I&#39;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(&quot;webclientManager&quot;) 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(&quot;customclient&quot;);
Function&lt;String, String&gt; httpsProxyPassword = username -&gt; proxyPassword;
HttpClient client = HttpClient.create()
.proxy(proxy -&gt; 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>

huangapple
  • 本文由 发表于 2023年5月29日 16:19:03
  • 转载请务必保留本文链接:https://go.coder-hub.com/76355711.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定