java.net
has a simple getServerCertificates
in its API (example follows). I was looking for a similar operation in reactor-netty, and if not there, in any other reactive API for spring-boot/webflux/HttpClient.
This operation (client reads certificate) does not seem possible in reactor-netty. Is it? If it isn't is there an alternative method in another spring-boot component to do this?
package com.example.readCertificate.service;
import java.net.URL;
import java.securiiity.cert.Certificate;
import javax.net.ssl.HttpsURLConnection;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
public class ShowCert {
private Logger logger = LogManager.getLogger();
public void showCert(String url) {
try {
URL destinationURL = new URL(url);
HttpsURLConnection connection = (HttpsURLConnection) destinationURL.openConnection();
connection.connect();
Certificate[] certificates = connection.getServerCertificates();
for (Certificate certificate : certificates) {
logger.info("certificate is:" + certificate);
}
} catch (Exception e) {
logger.error(e);
}
}
}
In WebClient from Spring WebFlux we usually use netty as backend. We provide a bean ReactorClientHttpConnector
in which we create netty http-client.
For handling SSL netty uses handler within the channel pipeline.
Here I'm putting a callback to event doOnConnected()
and accesing the SSL handler and SSLSession
.
SSLSession
provides methods getPeerCertificates(), getLocalCertificates()
, so we can get access to certificates here.
@Bean
public ReactorClientHttpConnector reactorClientHttpConnector() {
return new ReactorClientHttpConnector(
HttpClient.create()
.doOnConnected(connection -> {
ChannelPipeline pipeline = connection.channel().pipeline();
Optional.ofNullable(pipeline)
.map(p -> p.get(SslHandler.class))
.map(SslHandler::engine)
.map(SSLEngine::getSession)
.ifPresent(sslSession -> {
try {
Certificate[] peerCertificates = sslSession.getPeerCertificates();
if (Objects.nonNull(peerCertificates)) {
Stream.of(peerCertificates)
.forEach(System.out::println);
}
} catch (Exception e) {
e.printStackTrace();
}
});
})
);
}
And create your WebClient:
@Bean
public WebClient httpsClient() {
return WebClient.builder()
.clientConnector(reactorClientHttpConnector())
.baseUrl("https://secured-resource.com)
.build();
}
Then while making http-call with this httpsClient bean you should see the results in your console