Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to configure Spring RestTemplate with SSL (in Spring @MVC)

I want to configure my Spring @MVC stub application's Spring RestTemplate with SSL for communicate to REST base https application, that deployed on Tomcat server (Spring 3, Tomcat 7). I have done up to now my works by refer this link. Now I have not any idea how to use these generated certificates with Spring RestTemplate, Can anyone have some idea please help me. Thanks. Up to now things I have done,

//Spring Security xml Configurations

   <http>
    <intercept-url pattern="/login" access="IS_AUTHENTICATED_ANONYMOUSLY" requires-channel="https"/>      
    <http-basic/></http> 

//Configurations for enable SSL with Tomcat

<Connector port="8443" protocol="org.apache.coyote.http11.Http11NioProtocol" maxThreads="200"
    scheme="https" secure="true" SSLEnabled="true"
    keystoreFile="C:\Users\Channa\.keystore" keystorePass="changeit"
    clientAuth="false" sslProtocol="TLS"/>

For generating Keys, certificates etc,

//Generate client and server keys:

F:\jdk1.6.0_23\bin>keytool -genkey -keystore keystore_client -alias clientKey -dname "CN=localhost, OU=Dev, O=MyBusiness, L=Colombo, S=Westen, C=SL"
F:\jdk1.6.0_23\bin>keytool -genkey -keystore keystore_server -alias serverKey -dname "CN=localhost, OU=Dev, O=MyBusiness, L=Colombo, S=Westen, C=SL"

//Generate client and server certificates:

F:\jdk1.6.0_23\bin>keytool -export -alias clientKey -rfc -keystore keystore_client > client.cert F:\jdk1.6.0_23\bin>keytool -export -alias serverKey -rfc -keystore keystore_server > server.cert

//Import certificates to corresponding truststores:

F:\jdk1.6.0_23\bin>keytool -import -alias clientCert -file client.cert -keystore truststore_server F:\jdk1.6.0_23\bin>keytool -import -alias serverCert -file server.cert -keystore truststore_client

//Spring RestTemplate configurations

<!--Http client-->
<bean id="httpClient" class="org.apache.commons.httpclient.HttpClient">
    <constructor-arg ref="httpClientParams"/>
    <property name="state" ref="httpState"/>
</bean>

<!--Http state-->
<bean id="httpState" class="com.org.imc.test.stub.http.CustomHttpState">
    <property name="credentials" ref="usernamePasswordCredentials"/>
</bean>

<!--User name password credentials-->
<bean id="usernamePasswordCredentials" class="org.apache.commons.httpclient.UsernamePasswordCredentials"/>

<!--Http client-->
<bean id="httpClientFactory" class="org.springframework.http.client.CommonsClientHttpRequestFactory">
    <constructor-arg ref="httpClient"/>
</bean>

<!--RestTemplate-->
<bean id="restTemplate" class="org.springframework.web.client.RestTemplate">
    <constructor-arg ref="httpClientFactory"/>
</bean>

//Https URL going to access

ResponseEntity<User> rECreateUser = restTemplate.postForEntity("https://127.0.0.1:8443/skeleton-1.0/login", user, User.class);

//Exception currently I got:

org.springframework.web.client.ResourceAccessException: I/O error: sun.security.validator.ValidatorException: 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: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target

like image 793
Channa Avatar asked Oct 27 '11 09:10

Channa


People also ask

Does RestTemplate use ObjectMapper?

So, by simply using the RestTemplateBuilder our RestTemplate will automatically use a MappingJackson2HttpMessageConverter configured with an ObjectMapper that uses the required ParameterNamesModule.


2 Answers

This is because SSL certificate of the service you are calling is not signed by a trusted certificate authority. The workaround is to import the certificate into the certificate trust store (cacerts) of your JRE.

  1. download the cert by opening the URL in a browser, click the lock icon in the browser's address bar.
  2. Once you have a .cer file execute the below command

    keytool -import -keystore jdk1.8.0_77/jre/lib/security/cacerts -file ~/test.cer -alias test
    
like image 130
Peter Szanto Avatar answered Oct 15 '22 16:10

Peter Szanto


Variant for Spring Boot:

  1. Add dependency:

     implementation 'org.apache.httpcomponents:httpclient:4.5'    
    
  2. Provide RestTemplate bean:

@Bean
private RestTemplate restTemplate() {
        SSLContext sslContext = buildSslContext();
        SSLConnectionSocketFactory socketFactory = new SSLConnectionSocketFactory(sslContext);

        HttpClient httpClient = HttpClients.custom()
                .setSSLSocketFactory(socketFactory)
                .build();

        HttpComponentsClientHttpRequestFactory factory = new HttpComponentsClientHttpRequestFactory(httpClient);

        return new RestTemplate(factory);
    }

private SSLContext buildSslContext() {
        try {
            char[] keyStorePassword = sslProperties.getKeyStorePassword();
            return new SSLContextBuilder()
                    .loadKeyMaterial(
                            KeyStore.getInstance(new File(sslProperties.getKeyStore()), keyStorePassword),
                            keyStorePassword
                    ).build();
        } catch (Exception ex) {
            throw new IllegalStateException("Unable to instantiate SSL context", ex);
        } finally {
            sslProperties.setKeyStorePassword(null);
            sslProperties.setTrustStorePassword(null);
        }
    }
  1. Provide required SSL properties in your application.properties or application.yaml file:
server:
    ssl:
        enabled: true
        key-store: /path/to/key.keystore
        key-store-password: password
        key-alias: alias
        trust-store: /path/to/truststore
        trust-store-password: password

That's it. Now you can see your Tomcat is starting on 8080 (or another port) (https). Alternatively, you can use my spring boot starter

like image 41
Eugene Lesnov Avatar answered Oct 15 '22 15:10

Eugene Lesnov