How should I consume rest web service with ssl

I am supposed to write client which must fetch data from web service. I am follow this guide: https://spring.io/guides/gs/consuming-rest/ The website has https. My code:

@SpringBootApplication
public class TransportApplication {


    private static final Logger log = LoggerFactory.getLogger(TransportApplication.class);

    public static void main(String[] args) {
        SpringApplication.run(TransportApplication.class, args);
    }

    @Bean
    public RestTemplate restTemplate(RestTemplateBuilder builder) {
        return builder.build();
    }

    @Bean
    public CommandLineRunner run(RestTemplate restTemplate) throws Exception {
        return args -> {
            ResponseEntity<String> response = restTemplate.getForEntity("https://XXXXXX", String.class);
            log.info(response.toString());
        };
    }
}

When I run my program I get this exception:

Error starting ApplicationContext. To display the conditions report re-run your application with 'debug' enabled.
2021-03-25 23:23:31.809 ERROR 12700 --- [  restartedMain] o.s.boot.SpringApplication               : Application run failed

java.lang.IllegalStateException: Failed to execute CommandLineRunner
    at org.springframework.boot.SpringApplication.callRunner(SpringApplication.java:807) ~[spring-boot-2.4.3.jar:2.4.3]
    at org.springframework.boot.SpringApplication.callRunners(SpringApplication.java:788) ~[spring-boot-2.4.3.jar:2.4.3]
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:333) ~[spring-boot-2.4.3.jar:2.4.3]
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:1311) ~[spring-boot-2.4.3.jar:2.4.3]
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:1300) ~[spring-boot-2.4.3.jar:2.4.3]
    at com.example.demo.TransportApplication.main(TransportApplication.java:20) ~[classes/:na]
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[na:na]
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:64) ~[na:na]
    at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) ~[na:na]
    at java.base/java.lang.reflect.Method.invoke(Method.java:564) ~[na:na]
    at org.springframework.boot.devtools.restart.RestartLauncher.run(RestartLauncher.java:49) ~[spring-boot-devtools-2.4.3.jar:2.4.3]
Caused by: org.springframework.web.client.ResourceAccessException: I/O error on GET request for "https://avl2.telematika.lt/xml/p8tpzv3yqnza7pa28wx4p8rn2pyk3gwx.php": PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target; nested exception is javax.net.ssl.SSLHandshakeException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
    at org.springframework.web.client.RestTemplate.doExecute(RestTemplate.java:785) ~[spring-web-5.3.4.jar:5.3.4]
    at org.springframework.web.client.RestTemplate.execute(RestTemplate.java:711) ~[spring-web-5.3.4.jar:5.3.4]
    at org.springframework.web.client.RestTemplate.getForEntity(RestTemplate.java:361) ~[spring-web-5.3.4.jar:5.3.4]
    at com.example.demo.TransportApplication.lambda$run$0(TransportApplication.java:31) ~[classes/:na]
    at org.springframework.boot.SpringApplication.callRunner(SpringApplication.java:804) ~[spring-boot-2.4.3.jar:2.4.3]
    ... 10 common frames omitted
Caused by: javax.net.ssl.SSLHandshakeException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
    at java.base/sun.security.ssl.Alert.createSSLException(Alert.java:131) ~[na:na]
    at java.base/sun.security.ssl.TransportContext.fatal(TransportContext.java:369) ~[na:na]
    at java.base/sun.security.ssl.TransportContext.fatal(TransportContext.java:312) ~[na:na]
    at java.base/sun.security.ssl.TransportContext.fatal(TransportContext.java:307) ~[na:na]
    at java.base/sun.security.ssl.CertificateMessage$T13CertificateConsumer.checkServerCerts(CertificateMessage.java:1357) ~[na:na]
    at java.base/sun.security.ssl.CertificateMessage$T13CertificateConsumer.onConsumeCertificate(CertificateMessage.java:1232) ~[na:na]
    at java.base/sun.security.ssl.CertificateMessage$T13CertificateConsumer.consume(CertificateMessage.java:1175) ~[na:na]
    at java.base/sun.security.ssl.SSLHandshake.consume(SSLHandshake.java:396) ~[na:na]
    at java.base/sun.security.ssl.HandshakeContext.dispatch(HandshakeContext.java:480) ~[na:na]
    at java.base/sun.security.ssl.HandshakeContext.dispatch(HandshakeContext.java:458) ~[na:na]
    at java.base/sun.security.ssl.TransportContext.dispatch(TransportContext.java:199) ~[na:na]
    at java.base/sun.security.ssl.SSLTransport.decode(SSLTransport.java:171) ~[na:na]
    at java.base/sun.security.ssl.SSLSocketImpl.decode(SSLSocketImpl.java:1488) ~[na:na]
    at java.base/sun.security.ssl.SSLSocketImpl.readHandshakeRecord(SSLSocketImpl.java:1394) ~[na:na]
    at java.base/sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:441) ~[na:na]
    at java.base/sun.security.ssl.SSLSocketImpl.startHandshake(SSLSocketImpl.java:412) ~[na:na]
    at java.base/sun.net.www.protocol.https.HttpsClient.afterConnect(HttpsClient.java:567) ~[na:na]
    at java.base/sun.net.www.protocol.https.AbstractDelegateHttpsURLConnection.connect(AbstractDelegateHttpsURLConnection.java:183) ~[na:na]
    at java.base/sun.net.www.protocol.https.HttpsURLConnectionImpl.connect(HttpsURLConnectionImpl.java:142) ~[na:na]
    at org.springframework.http.client.SimpleBufferingClientHttpRequest.executeInternal(SimpleBufferingClientHttpRequest.java:76) ~[spring-web-5.3.4.jar:5.3.4]
    at org.springframework.http.client.AbstractBufferingClientHttpRequest.executeInternal(AbstractBufferingClientHttpRequest.java:48) ~[spring-web-5.3.4.jar:5.3.4]
    at org.springframework.http.client.AbstractClientHttpRequest.execute(AbstractClientHttpRequest.java:66) ~[spring-web-5.3.4.jar:5.3.4]
    at org.springframework.web.client.RestTemplate.doExecute(RestTemplate.java:776) ~[spring-web-5.3.4.jar:5.3.4]
    ... 14 common frames omitted
Caused by: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
    at java.base/sun.security.validator.PKIXValidator.doBuild(PKIXValidator.java:439) ~[na:na]
    at java.base/sun.security.validator.PKIXValidator.engineValidate(PKIXValidator.java:306) ~[na:na]
    at java.base/sun.security.validator.Validator.validate(Validator.java:264) ~[na:na]
    at java.base/sun.security.ssl.X509TrustManagerImpl.checkTrusted(X509TrustManagerImpl.java:231) ~[na:na]
    at java.base/sun.security.ssl.X509TrustManagerImpl.checkServerTrusted(X509TrustManagerImpl.java:132) ~[na:na]
    at java.base/sun.security.ssl.CertificateMessage$T13CertificateConsumer.checkServerCerts(CertificateMessage.java:1341) ~[na:na]
    ... 32 common frames omitted
Caused by: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
    at java.base/sun.security.provider.certpath.SunCertPathBuilder.build(SunCertPathBuilder.java:141) ~[na:na]
    at java.base/sun.security.provider.certpath.SunCertPathBuilder.engineBuild(SunCertPathBuilder.java:126) ~[na:na]
    at java.base/java.security.cert.CertPathBuilder.build(CertPathBuilder.java:297) ~[na:na]
    at java.base/sun.security.validator.PKIXValidator.doBuild(PKIXValidator.java:434) ~[na:na]
    ... 37 common frames omitted

It seems like I need to enable ssl. Okay, I have follow few guides and they don’t really help me. One of them: https://snmaddula.bitbucket.io/enable-https-in-spring-boot-app/ I also tried to disable ssl(I did it in postman) it seems like some of solutions are outdated or I don’t get how to use them. Such an example is the best answer from this post: Disabling SSL Certificate Validation in Spring RestTemplate Please help me, I think my task must be very easy but this I have already spent a few hours trying to make this program work.

Answer

You need to add the certificate of the rest web service to the truststore file of the used JVM located at %JAVA_HOME%libsecuritycacerts.

For getting the certificate open the url you are calling in a chrome and download it. You can download the certificate by clicking on site information icon then details than copy to file as below: enter image description here

Afterwards open git bash by running it as administrator and run this command:

keytool -import -alias alias_of_your_choice -keystore  '%JAVA_HOME%libsecuritycacerts' -file filepath

After adding it to the keystore you might want to restart the pc.

Leave a Reply

Your email address will not be published. Required fields are marked *