Invoking Secured WebServices

Accepting TrustStrategy without TrustMaterial

This tutorial demonstrates the invocation of secured webservices using RestTemplate

— tvajjala

When your web services are secured by HTTPs(self signed) protocol, and you are trying to access them using RestTemplate you will get following exceptions:

unable to find valid certification path to requested target; nested exception is javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target

There are two ways we can make it work.

  1. Accepting TrustStrategy without TrustMaterial

  2. Loading TrustMaterial into SSLContext (Recommended)

Accepting TrustStrategy without TrustMaterial

We just ignore https certification by customizing restTemplate as shown below

    /**
     * default restTemplates since we are skipping sslVerification
     *
     * @return RestTemplate {@link RestTemplate}
     * @throws Exception {@link Exception}
     */
    @Bean
    public RestTemplate restTemplate() throws Exception {

        return new RestTemplate(new HttpComponentsClientHttpRequestFactory(httpClient()));
    }


    /**
     * default httpClient
     *
     * @return httpClient
     * @throws Exception exception
     */
    HttpClient httpClient() throws Exception {
        SSLConnectionSocketFactory csf = new SSLConnectionSocketFactory(getSSLContext(false));
        return HttpClients.custom().setSSLSocketFactory(csf).build();
    }


    /**
     * Create sslContext in a two different ways
     *
     * @param trusted IsTrusted
     * @return sslContext
     * @throws Exception exception
     */
    SSLContext getSSLContext(boolean trusted) throws Exception {

        if (trusted) {
            return new SSLContextBuilder().loadTrustMaterial(new ClassPathResource("swagger.jks").getFile(), "swagger".toCharArray()).build();
        }

        TrustStrategy acceptingTrustStrategy = (X509Certificate[] chain, String authType) -> true;
        return SSLContexts.custom().loadTrustMaterial(null, acceptingTrustStrategy).build();

    }

Create JKS file and load that file into trust material.

    /**
     * trusted RestTemplate
     *
     * @return RestTemplate {@link RestTemplate}
     * @throws Exception
     */
    @Bean
    RestTemplate trustedRestTemplate() throws Exception {
        return new RestTemplate(new HttpComponentsClientHttpRequestFactory(trustedHttpClient()));
    }


    /**
     * keyStore based httpClient trusted
     *
     * @return HttpClient  {@link HttpClient}
     * @throws Exception exception
     */
    HttpClient trustedHttpClient() throws Exception {
        HttpClientBuilder builder = HttpClientBuilder.create();
        builder.setSSLContext(getSSLContext(true));
        return builder.build();
    }

Generate JKS file from .cer

  • Export the certificate to a file from your https webServices

Go to your browser export certifcate (swagger.cer)
  • Import into JKS

Import the certificate to trusted domain cacerts using the keytool.

But you need to import it to the keystore that your java_home uses when running your programs above

The command below will add certificate file "swagger.cer" to keystore in file "cacerts.jks".

The alias is "swagger" :

keytool.sh
keytool -import -trustcacerts -alias swagger -file swagger.cer -keystore cacerts.jks

Verify all imported certificates in JKS file with below command

list.sh
keytool -list -v -keystore swagger.jks

Source Code

Refer github project for complete source code of this tutorial

Comments

Popular posts from this blog

IBM Datapower GatewayScript

Spring boot Kafka Integration

Spring boot SOAP Web Service Performance