javaspring-bootssltruststore

SpringBoot RestClient (not WebClient, not RestTemplate) with InsecureTrustManagerFactory.INSTANCE with SslBundle


There is a third-party REST endpoint I am trying to interact with. This third-party API requires certificate authentication. To do so, I am using the following, leveraging Spring SslBundle:

@Bean
public RestClient restClient(RestClient.Builder builder, RestClientSsl ssl) {
    return builder.baseUrl("https://the-secure-api.com/api")
                .defaultHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE, HttpHeaders.ACCEPT, MediaType.APPLICATION_JSON_VALUE)
                .apply(ssl.fromBundle("mybundle"))
                .build();
}
spring:
  ssl:
    bundle:
      jks:
        mybundle:
          keystore:
            location: C:\\ssl\\keystore.p12
            password: 123
            type: PKCS12
          truststore:
            location: C:\\ssl\\truststore.p12
            password: 123
            type: PKCS12
          reload-on-update: true

This is working fine. The third-party app confirms they can see my client certificate being sent to them. I am also validating their certificate with my trust store. I would like to disable SSL validation on my side. I tried to remove this from the property, leaving .apply(ssl.fromBundle("mybundle"))

spring:
  ssl:
    bundle:
      jks:
        mybundle:
          keystore:
            location: C:\\ssl\\keystore.p12
            password: 123
            type: PKCS12
          reload-on-update: true

And thought this would equal to InsecureTrustManagerFactory.INSTANCE , which is not.

Question: How to disable ssl verification (trust insecure host) with Spring Ssl Bundle (and hopefully, without having to go to use RestTemplate again?


Solution

  • Try something like this (Need hand on more with these code snippets for checking)

    import org.springframework.http.client.ClientHttpRequestFactory;
    import org.springframework.http.client.JdkClientHttpRequestFactory;
    import org.springframework.web.client.RestClient;
    
    import javax.net.ssl.*;
    import java.net.http.HttpClient;
    import java.security.cert.X509Certificate;
    import java.time.Duration;
    
    public class InsecureRestClient {
    
        public static RestClient create() throws Exception {
            // Trust manager that does not validate certificate chains
            TrustManager[] trustAllCerts = new TrustManager[]{
                new X509TrustManager() {
                    public X509Certificate[] getAcceptedIssuers() { return new X509Certificate[0]; }
                    public void checkClientTrusted(X509Certificate[] certs, String authType) {}
                    public void checkServerTrusted(X509Certificate[] certs, String authType) {}
                }
            };
    
            // Install the all-trusting trust manager
            SSLContext sslContext = SSLContext.getInstance("TLS");
            sslContext.init(null, trustAllCerts, new java.security.SecureRandom());
    
            // Create JDK HttpClient with disabled hostname verification
            HttpClient httpClient = HttpClient.newBuilder()
                    .sslContext(sslContext)
                    .connectTimeout(Duration.ofSeconds(10))
                    .sslParameters(new SSLParameters() {{
                        setEndpointIdentificationAlgorithm(null); // Disables hostname verification.
                    }})
                    .build();
    
            // Wrap in Spring’s request factory
            ClientHttpRequestFactory requestFactory = new JdkClientHttpRequestFactory(httpClient);
    
            return RestClient.builder()
                    .requestFactory(requestFactory)
                    .build();
        }
    }
    

    and

    RestClient restClient = InsecureRestClient.create();
    
    String response = restClient.get()
            .uri("https://self-signed.badssl.com/")
            .retrieve()
            .body(String.class);
    
    System.out.println(response);
    

    or you try something from HttpClient https://www.javadoc.io/doc/org.apache.httpcomponents/httpclient/4.5.3/org/apache/http/conn/ssl/NoopHostnameVerifier.html

    Related URLs: