在 Spring Boot 2.0 中使用 Web Client 访问 HTTPS RESTful 服务抛出异常 [英] Access HTTPS RESTful service using Web Client in Spring Boot 2.0 throwing exception

查看:68
本文介绍了在 Spring Boot 2.0 中使用 Web Client 访问 HTTPS RESTful 服务抛出异常的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我必须访问一个 https 休息网络服务 (https://example.com)由客户端提供,其中包含 2 个 .cer 文件.

I have to access one https rest web service(https://example.com) for which certificate has been provided by the client which contains 2 .cer files.

我已经创建了keystore.jkstruststore.jks 文件,并且将.cer 文件导入到jks 文件.使用下面的命令

I have created keystore.jks and truststore.jks files and imported the .cer files to jks file. by using the below command

keytool -genkeypair -alias abcd -keyalg RSA -sigalg garegar -keysize 2048 -storetype jks -keystore keystore.jks -validity 365 -storepass changeit

keytool -import -alias abcd -trustcacerts -file free/ca_bundle.cer -keystore keystore.jksccessfull

我已将所有属性添加到 application.yml

I have added all properties to application.yml

   truststore-location: 
   keystore-location: 
   truststore-password: 
   keystore-password: 
   key-alias:

在配置类中创建 bean 以获取 webclient 对象.

Created the bean in configuration class to get the webclient object.

@Data
@NoArgsConstructor
@AllArgsConstructor
@Configuration
public class WebServiceRestConfig {

    @Value(value = "${wcc.rest.endpoint}")
    private String url;

    @Value(value = "${wcc.dam.username}")
    private String username;

    @Value(value = "${wcc.dam.password}")
    private String password;

    @Value(value = "${ssl.truststore-location}")
    private String trustStore;

    @Value(value = "${ssl.keystore-location}")
    private String keyStore;

    @Value(value = "${ssl.truststore-password}")
    private String trustStorePassword;

    @Value(value = "${ssl.keystore-password}")
    private String keyStorePassword;

    @Value(value = "${ssl.key-alias}")
    private String keyAlias;




    @Bean
    WebClientCustomizer configureWebclient() {

        return (WebClient.Builder webClientBuilder) -> {
            SslContext sslContext;
            final PrivateKey privateKey;
            final X509Certificate[] certificates;
            try {
                final KeyStore trustStore;
                final KeyStore keyStore;
                trustStore = KeyStore.getInstance(KeyStore.getDefaultType());
                trustStore.load(new FileInputStream(ResourceUtils.getFile(getTrustStore())),
                        trustStorePassword.toCharArray());
                keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
                keyStore.load(new FileInputStream(ResourceUtils.getFile(getKeyStore())), keyStorePassword.toCharArray());
                List<Certificate> certificateList = Collections.list(trustStore.aliases()).stream().filter(t -> {
                    try {
                        return trustStore.isCertificateEntry(t);
                    } catch (KeyStoreException e1) {
                        throw new RuntimeException("Error reading truststore", e1);
                    }
                }).map(t -> {
                    try {
                        return trustStore.getCertificate(t);
                    } catch (KeyStoreException e2) {
                        throw new RuntimeException("Error reading truststore", e2);
                    }
                }).collect(Collectors.toList());
                certificates = certificateList.toArray(new X509Certificate[certificateList.size()]);
                privateKey = (PrivateKey) keyStore.getKey(keyAlias, keyStorePassword.toCharArray());
                Certificate[] certChain = keyStore.getCertificateChain(keyAlias);
                X509Certificate[] x509CertificateChain = Arrays.stream(certChain)
                        .map(certificate -> (X509Certificate) certificate).collect(Collectors.toList())
                        .toArray(new X509Certificate[certChain.length]);
                sslContext = SslContextBuilder.forClient().keyManager(privateKey, keyStorePassword, x509CertificateChain)
                        .trustManager(certificates).build();

                HttpClient httpClient = HttpClient.create()
                        .secure(sslContextSpec -> sslContextSpec.sslContext(sslContext));
                ClientHttpConnector connector = new ReactorClientHttpConnector(httpClient);
                webClientBuilder.clientConnector(connector).baseUrl(getUrl()).build();

            } catch (KeyStoreException e) {
                throw new RuntimeException(e);
            }catch(CertificateException e) {
                throw new RuntimeException(e);
            }catch(NoSuchAlgorithmException e) {
                throw new RuntimeException(e);
            }catch(IOException e) {
                throw new RuntimeException(e);
            }catch(UnrecoverableKeyException e) {
                throw new RuntimeException(e);
            }
        };
    }

}

但是当我运行应用程序时,我遇到了异常

But when i am running the application I am getting below exception

SEVERE: Servlet.service() for servlet [dispatcherServlet] in context with path [] threw exception [Request processing failed; nested exception is reactor.core.Exceptions$ReactiveException: javax.net.ssl.SSLHandshakeException: General SSLEngine problem] with root cause
sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
    at sun.security.provider.certpath.SunCertPathBuilder.build(SunCertPathBuilder.java:145)
    at sun.security.provider.certpath.SunCertPathBuilder.engineBuild(SunCertPathBuilder.java:131)
    at java.security.cert.CertPathBuilder.build(CertPathBuilder.java:280)
    at sun.security.validator.PKIXValidator.doBuild(PKIXValidator.java:382)
    at sun.security.validator.PKIXValidator.engineValidate(PKIXValidator.java:292)
    at sun.security.validator.Validator.validate(Validator.java:260)
    at sun.security.ssl.X509TrustManagerImpl.validate(X509TrustManagerImpl.java:324)
    at sun.security.ssl.X509TrustManagerImpl.checkTrusted(X509TrustManagerImpl.java:281)
    at sun.security.ssl.X509TrustManagerImpl.checkServerTrusted(X509TrustManagerImpl.java:136)
    at sun.security.ssl.ClientHandshaker.serverCertificate(ClientHandshaker.java:1465)
    at sun.security.ssl.ClientHandshaker.processMessage(ClientHandshaker.java:212)
    at sun.security.ssl.Handshaker.processLoop(Handshaker.java:969)

现在我完全不知道该怎么做以及如何解决这个问题我需要在资源文件夹中添加任何东西还是我在这里遗漏了什么?

Right now I am completely clueless what to do and how to resolve this do i need to add anything in resources folder or am i missing something here?

推荐答案

我遇到了类似的问题:

@Bean("oAuth2")
public WebClient webOAuth2Client(ReactiveClientRegistrationRepository registration,
                           ServerOAuth2AuthorizedClientRepository clientRepository) {

    ServerOAuth2AuthorizedClientExchangeFilterFunction filter =
            new ServerOAuth2AuthorizedClientExchangeFilterFunction(
                    registration,
                    clientRepository);
    filter.setDefaultClientRegistrationId("oAuth2");
   

    return WebClient
            .builder()
            .filter(filter)
            .build();
}

在属性文件中类似:

    security:
    oauth2:
      client:
        provider:
          oAuth2:
            token-uri: url:port/auth/realms/SCRealm/protocol/openid-connect/token
        registration:
          oAuth2:
            clientId: client_id
            clientSecret: client_secret
            authorizationGrantType: client_credentials
            clientAuthenticationMethod: post

在主应用程序类中:

System.setProperty("-Dio.netty.handler.ssl.noOpenSsl","true");
System.setProperty("javax.net.ssl.trustStore", "keyStore.jks");
System.setProperty("javax.net.ssl.trustStoreType", "JKS");
System.setProperty("javax.net.ssl.trustStorePassword", "any_strong_pass");

这篇关于在 Spring Boot 2.0 中使用 Web Client 访问 HTTPS RESTful 服务抛出异常的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆