cipley
cipley

Reputation: 1112

Spring Boot WebCLient accept Self Signed Certificate, but not with InsecureTrustManagerFactory

I'm trying to build a REST client using Spring Boot and utilizing WebClient, however I'm conflicted when trying to config HTTPS call to a REST API.

When using RestTemplate, I was able to get self signed certificate working by using TrustSelfSignedStrategy(), thus even when the certificate is self signed, it is still being validated for its hostname, expiry date, etc.

In WebClient, so far I only found the way self signed certificate is by utilizing InsecureTrustManagerFactory, however this will cause the whole validation to be skipped as well, effectively void the purpose of using HTTPS in the first place.

As quoted from Netty documentations:

An insecure TrustManagerFactory that trusts all X.509 certificates without any verification.

NOTE: Never use this TrustManagerFactory in production. It is purely for testing purposes, and thus it is very insecure.

Is there any way I can use self signed certificate in WebClient without having to dismantle all the verification?

Upvotes: 1

Views: 10712

Answers (1)

Hakan54
Hakan54

Reputation: 3871

Yes, you can use a self signed certificate. What you need to do is add the self signed certificate into a java keystore and load it into your application by getting the keystore and transforming it into a TrustManager. Afterword you can supply the TrustManager to the SslContextBuilder which is needed for configuring the WebClient based on Netty. See below for an example:

Path truststorePath = Paths.get(/path/to/your/truststore)
InputStream truststoreInputStream = Files.newInputStream(truststorePath, StandardOpenOption.READ)

KeyStore truststore = KeyStore.getInstance(KeyStore.getDefaultType());
truststore.load(truststoreInputStream, truststorePassword);

TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
trustManagerFactory.init(truststore);

SslContext sslContext = SslContextBuilder.forClient()
        .trustManager(trustManagerFactory)
        .build()

HttpClient httpClient = HttpClient.create()
        .secure(sslSpec -> sslSpec.sslContext(sslContext));

WebClient.builder()
        .clientConnector(new ReactorClientHttpConnector(httpClient))
        .build()

Upvotes: 3

Related Questions