2

I wrote a 2-way authetication restful service cleint to consume a secured restful web service on port 8443 over https. Here are parts of application.properties:

trust.store=classpath:truststore.jks

trust.store.password=xyz123

key.store=classpath:keystore.jks

key.store.password=xyz123

Below are two ways to configure RestTemplate

@Configuration
public class SSLTemplate {

    @Value("${key.store}")
    private String  keyStore;
    @Value("${key.store.password}")
    private String keyStorePassword;
    @Value("${trust.store}")
    private String  trustStore;
    @Value("${trust.store.password}")
    private String trustStorePassword;

    @Bean
    public RestTemplate restTemplate(RestTemplateBuilder builder) throws Exception {
        SSLContext sslContext = SSLContextBuilder.create()
                .loadKeyMaterial(ResourceUtils.getFile(keyStore), keyStorePassword.toCharArray(), keyStorePassword.toCharArray())
                .loadTrustMaterial(ResourceUtils.getFile(trustStoreF), trustStorePassword.toCharArray())
                .build();
    ...
}

@Configuration
public class SSLTemplate {

    @Value("${key.store}")
    private Resource keyStoreR;
    @Value("${key.store.password}")
    private String keyStorePassword;
    @Value("${trust.store}")
    private Resource trustStoreR;
    @Value("${trust.store.password}")
    private String trustStorePassword;

    @Bean
    public RestTemplate restTemplate(RestTemplateBuilder builder) throws Exception {
        SSLContext sslContext = SSLContextBuilder.create()
                .loadKeyMaterial(keyStoreR.getURL(), keyStorePassword.toCharArray(), keyStorePassword.toCharArray())
                .loadTrustMaterial(trustStoreR.getURL(), trustStorePassword.toCharArray())
                .build();
    ...
}

When I run the app via bootRun or within Eclipse, both of them work.

But when I use jar launcer

java -jar app.jar

I got below exception.

Bean instantiation via factory method failed; nested exception is org.springframework.beans.BeanInstantiation Exception: Failed to instantiate [org.springframework.web.client.RestTemplate]: Factory method 'restTemplate' threw exception; nested exception is java.io.FileNotFoundException: URL cannot be resolved to absolute file path because it does not reside in the file system: jar:file:/C:/build/libs/app.jar!/BOOT-INF/classes!/truststore.jks

I have also tried

java -Djavax.net.ssl.trustStore=truststore.jks -Djavax.net.ssl.trustStorePassword=xyz123 -Djavax.net.ssl.keyStore=keystore.jks -Djavax.net.ssl.keyStorePassword=xyz123 -jar app.jar

and got the same exception. Any help will be really appreciated.

Vadim Kotov
  • 8,084
  • 8
  • 48
  • 62
user3593086
  • 43
  • 1
  • 6
  • Probably, the problem is related to the classpath. Are your `truststore.jks` and `keystore.jks` files located in the same directory, from which you run `java -jar app.jar` ? – Vüsal Feb 06 '19 at 07:46
  • Yes the app.jar, truststore.jks, and keystore.jks are in the same directory where I run java -jar app.jar. – user3593086 Feb 06 '19 at 14:19

1 Answers1

0

Try using resource.getInputStream() instead of resource.getFile() as, resource.getFile() in Spring tries to access a file system path but it can not access a path in your JAR

This link has a rich content and do take a look at Andy's answer here

Sample example:

Resource resource = resourceLoader.getResource("classpath:GeoLite2-Country.mmdb");
            InputStream dbAsStream = resource.getInputStream();

and do you have use full path

-Djavax.net.ssl.trustStore=something/like/this/truststore.jks
Clover
  • 507
  • 7
  • 22