Spring 5 WebClient using ssl
See an example using the insecure TrustManagerFactory , which trusts all X.509 certificates (including self-signed ones) without any verification. Important note from the documentation:
Never use this TrustManagerFactory in production. This is purely for testing purposes and therefore very insecure.
@Bean
public WebClient createWebClient() throws SSLException {
SslContext sslContext = SslContextBuilder
.forClient()
.trustManager(InsecureTrustManagerFactory.INSTANCE)
.build();
ClientHttpConnector httpConnector = new ReactorClientHttpConnector(opt -> opt.sslContext(sslContext));
return WebClient.builder(httpConnector).build();
}
source to share
Another way if you want to code production code is to create a spring bean like the one that the injected web client modifies using the settings from the spring-boot server where the trust store and key store are located. In the client, you only need to provide the keystore if you are using 2-way-ssl. Not sure why the ssl stuff is not preconfigured and easily injected like in the really cool spring-boot server setup.
import io.netty.handler.ssl.SslContext;
import io.netty.handler.ssl.SslContextBuilder;
.
.
.
@Bean
WebClientCustomizer configureWebclient(@Value("${server.ssl.trust-store}") String trustStorePath, @Value("${server.ssl.trust-store-password}") String trustStorePass,
@Value("${server.ssl.key-store}") String keyStorePath, @Value("${server.ssl.key-store-password}") String keyStorePass, @Value("${server.ssl.key-alias}") String keyAlias) {
return new WebClientCustomizer() {
@Override
public void customize(Builder webClientBuilder) {
SslContext sslContext;
try {
KeyStore trustStore = KeyStore.getInstance(KeyStore.getDefaultType());
trustStore.load(new FileInputStream(ResourceUtils.getFile(trustStorePath)), trustStorePass.toCharArray());
List<Certificate> certificateCollcetion = Collections.list(trustStore.aliases()).stream().filter(t -> {
try {
return trustStore.isCertificateEntry(t);
} catch (KeyStoreException e1) {
throw new RuntimeException("Error reading truststore", e1);
}
}).map(t -> {
try {
return trustStore.getCertificate(t);
} catch (KeyStoreException e2) {
throw new RuntimeException("Error reading truststore", e2);
}
}).collect(Collectors.toList());
KeyStore keyStore = KeyStore.getInstance(KeyStore.getDefaultType());
keyStore.load(new FileInputStream(ResourceUtils.getFile(keyStorePath)), keyStorePass.toCharArray());
sslContext = SslContextBuilder.forClient()
.keyManager((PrivateKey) keyStore.getKey(keyAlias, keyStorePass.toCharArray()))
.trustManager((X509Certificate[]) certificateCollcetion.toArray(new X509Certificate[certificateCollcetion.size()]))
.build();
} catch (Exception e) {
log.error("Error creating web client", e);
throw new RuntimeException(e);
}
ClientHttpConnector connector = new ReactorClientHttpConnector((opt) -> {
opt.sslContext(sslContext);
});
webClientBuilder.clientConnector(connector);
}
};
}
Here's the part where you are using the Webclient: import org.springframework.web.reactive.function.client.WebClient;
@Component
public class ClientComponent {
public ClientComponent(WebClient.Builder webClientBuilder, @Value("${url}") String url) {
this.client = webClientBuilder.baseUrl(solrUrl).build();
}
}
source to share