I am trying to accept all certificates, and/or accept self-signed certificates using Apache HTTPClient version 4.5 (tutorial link here)
One of the above approaches should work in case of self-signed certificates, but the weird thing is you are getting same exception in all the approaches.
I feel during SSL session establishment or handshaking protocol is not being accepted either by client or by server.
The best solution here is to debug the application.
In case of tomcat, add -Djavax.net.debug=all in setenv.sh or setenv.bat files and then restart the server.
Or you can follow this tutorial.
The OP just needed to change the port when connecting to SSL:
//For HTTPS
HttpHost httpstarget = new HttpHost("mysite.com", 443, "https");
//For HTTP
HttpHost httptarget = new HttpHost("mysite.com", 80, "http");
Very often you not only need to support self signed certificates, but also invoke multi-threaded requests, and so use a pooling connection manager. Here's how I do it:
private CloseableHttpClient newClient() throws KeyManagementException, NoSuchAlgorithmException, KeyStoreException {
SSLContext context = SSLContexts.custom()
.loadTrustMaterial(TrustSelfSignedStrategy.INSTANCE)
.build();
Registry<ConnectionSocketFactory> registry = RegistryBuilder.<ConnectionSocketFactory> create()
.register("http", PlainConnectionSocketFactory.INSTANCE)
.register("https", new SSLConnectionSocketFactory(context, NoopHostnameVerifier.INSTANCE))
.build();
PoolingHttpClientConnectionManager connectionManager = new PoolingHttpClientConnectionManager(registry);
return HttpClients.custom()
.setConnectionManager(connectionManager)
.build();
}
This problem is about SSL connection. When you try to connect to some resource https protocol requires to create secured connection. That means only your browser and website server know what data is being sent in requests bodies. This security is achieved by ssl certificates that stored on website and are being downloaded by your browser (or any other client, Apache Http Client in our case) with first connection to host. There are RSA256 encryption and many other cool things around. But in the end of a day: In case certificate is not registered or is invalid you will see certificate error (HTTPS connection is not secure). To fix certificate error website provider need to buy it for particular website or fix somehow e.g. https://www.register.com/ssl-certificates
however there is an bypass when you skip ssl verification with
(s, sslSession) -> true
that is security violation because you are not 100% sure that your data is secured, however this solution can used for testing or configuration when use test data and trusted websites
public static HttpClient newClient() {
SSLContext sslcontext = null;
try {
sslcontext = SSLContexts.custom().loadTrustMaterial(null, new TrustSelfSignedStrategy()).build();
} catch (NoSuchAlgorithmException | KeyManagementException | KeyStoreException e) {
e.printStackTrace();
}
SSLConnectionSocketFactory sslConnectionSocketFactory = new SSLConnectionSocketFactory(sslcontext,
(s, sslSession) -> true);
return HttpClients.custom().setSSLSocketFactory(sslConnectionSocketFactory)
.build();
}
I'm using Apache HttpClient 4.5.3 and none of the above solutions helped. I always got the error
PKIX Path building failed
.
I found the solution in http://www.baeldung.com/httpclient-ssl
Here's my code:
try {
SSLContext sslContext = new SSLContextBuilder()
.loadTrustMaterial(null, (certificate, authType) -> true).build();
httpClient = HttpClients.custom().setSSLContext(sslContext)
.setSSLHostnameVerifier(new NoopHostnameVerifier())
.build();
} catch (NoSuchAlgorithmException | KeyManagementException | KeyStoreException e) {
e.printStackTrace();
}