PKIX path building failed: sun.security.provider.certpath
Disable SSL validation in Spring RestTemplate
Upasana | July 23, 2020 | 3 min read | 13,826 views
We will disable SSL certificate verification and thus trust all kind of certificates whether valid or not in Spring Boot RestTemplate.
In non production environments, we often need to disable ssl certificate validation (self-signed, expired, non trusted root, etc) for testing purpose. We will configure RestTemplate to disable SSL validation and allow http requests to these hosts without throwing exception.
RestTemplate can give any of the below error if SSL certificate of the target host is not valid:
PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target
javax.net.ssl.SSLHandshakeException: PKIX path building failed
Reasons for invalid SSL certificate could be many, including:
-
Expired certificate
-
Self-signed certificate
-
Wrong host information in certificates
-
Revoked certificate
-
Untrusted root of certificate
Gradle setup
We will be using Spring Boot 2 environment for this article, but you are free to choose any other compatible version of Spring.
plugins {
id 'org.springframework.boot' version '2.3.1.RELEASE'
id 'java'
id 'io.spring.dependency-management' version '1.0.9.RELEASE'
}
group = 'com.shunya.tutorial'
version = '0.0.1-SNAPSHOT'
sourceCompatibility = '11'
repositories {
mavenCentral()
}
dependencies {
implementation 'org.springframework.boot:spring-boot-starter-web'
implementation 'org.apache.httpcomponents:httpclient:4.5.10'
testImplementation('org.springframework.boot:spring-boot-starter-test') {
exclude group: 'org.junit.vintage', module: 'junit-vintage-engine'
}
}
We have added Apache HttpClient
dependency to our project because that is required for customization of RestTemplate.
Creating RestTemplate Bean
Spring boot does not create any single auto-configured RestTemplate instance. It does, however, auto-configure a RestTemplateBuilder, which can be used to create RestTemplate instances when needed.
We will use RestTemplateBuilder to create a custom RestTemplate Bean that will trust all kind of (good or bad) SSL certificates. Please be aware this should never be done for any production environment.
import org.apache.http.conn.ssl.NoopHostnameVerifier;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.springframework.boot.web.client.RestTemplateBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.http.client.HttpComponentsClientHttpRequestFactory;
import org.springframework.web.client.RestTemplate;
import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;
import java.security.KeyManagementException;
import java.security.NoSuchAlgorithmException;
import java.security.cert.X509Certificate;
@Configuration
public class RestTemplateConfig {
@Bean
public RestTemplate restTemplate(RestTemplateBuilder builder) throws NoSuchAlgorithmException, KeyManagementException {
TrustManager[] trustAllCerts = new TrustManager[] {
new X509TrustManager() {
public java.security.cert.X509Certificate[] getAcceptedIssuers() {
return new X509Certificate[0];
}
public void checkClientTrusted(
java.security.cert.X509Certificate[] certs, String authType) {
}
public void checkServerTrusted(
java.security.cert.X509Certificate[] certs, String authType) {
}
}
}; (1)
SSLContext sslContext = SSLContext.getInstance("SSL");
sslContext.init(null, trustAllCerts, new java.security.SecureRandom()); (2)
CloseableHttpClient httpClient = HttpClients.custom()
.setSSLContext(sslContext)
.setSSLHostnameVerifier(NoopHostnameVerifier.INSTANCE)
.build(); (3)
HttpComponentsClientHttpRequestFactory customRequestFactory = new HttpComponentsClientHttpRequestFactory();
customRequestFactory.setHttpClient(httpClient);
return builder.requestFactory(() -> customRequestFactory).build(); (4)
}
}
1 | Creating trust manager that blindly trusts all kind of SSL certificates (good ones as well as bad ones) |
2 | Install trust manager to SSL Context |
3 | Create an HttpClient that uses the custom SSLContext and do not verify cert hostname |
4 | Create a RestTemplate that uses custom request factory |
If you do not want to use RestTemplateBuilder for configuring RestTemplate, then simply create a new instance of RestTemplate and pass it the customRequestFactory Object, as shown below:
...
class customRequestFactory = new HttpComponentsClientHttpRequestFactory();
customRequestFactory.setHttpClient(httpClient);
return new RestTemplate(customRequestFactory);
Now you can autowire this RestTemplate Bean anywhere you want to use it.
A simple startup runner can be used to test the RestTemplate’s behaviour.
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Component;
import org.springframework.web.client.RestTemplate;
@Component
public class StartupRunner implements ApplicationRunner {
@Autowired
private RestTemplate restTemplate;
@Override
public void run(ApplicationArguments args) throws Exception {
final ResponseEntity<String> responseEntity = restTemplate.getForEntity("https://self-signed.badssl.com/", String.class);
if(responseEntity.getStatusCode().is2xxSuccessful()) {
System.out.println(responseEntity.getBody());
}
}
}
This shall not throw any error this time.
Creating self signed certificate for testing
Refer to this article - Create self signed HttpClient and RestTemplate for testing
Reference
-
https://badssl.com/ This site can be used for testing all kind bad SSL stuff.
-
https://mvnrepository.com/artifact/org.apache.httpcomponents/httpclient You can get the latest version of HttpClient from here.
Top articles in this category:
- Disable SSL verification in Spring WebClient
- Spring RestTemplate Basic Authentication
- Send Gupshup SMS using Java API
- Redis rate limiter in Spring Boot
- Download a file using Spring RestTemplate
- N+1 problem in Hibernate & Spring Data JPA
- Table backed global counter in spring hibernate