When you need to support self-signed SSL certificates in your Apache HttpClient based application you can use the contributed EasySSLProtocolSocketFactory as described in the HttpClient docs.
Instead of using HttpClient’s HostConfiguration object directly you’d modify its protocol socket factory in your code like so:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 | ... if (config.isAllowSelfSignedCertificates()) { ProtocolSocketFactory factory = new EasySSLProtocolSocketFactory(); try { URI uri = new URI(config.getBaseUrl()); int port = uri.getPort(); if (port == -1) { port = 443; } Protocol easyHttps = new Protocol(uri.getScheme(), factory, port); hostConfiguration.setHost(uri.getHost(), port, easyHttps); } catch (URISyntaxException e) { throw new IOException("could not parse URI " + config.getBaseUrl(), e); } } ... |
Somewhere you’d instantiate a HttpClient object. Then you get its host config through HttpClient#getHostConfiguration() – I stored this in the hostConfiguration variable. The if, the config variable, checking for port, etc. is all my own code and has nothing to do with HttpClient directly.
There is one caveat, though! Never use absolute URIs against the HttpClient 3.x with the EasySSLProtocolSocketFactory in place! If you did you’d get the dreaded
1 | javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX path building failed: sun.security.provider.certpath.SunCertPathBuilderException: unable to find valid certification path to requested target |
I found that the HttpClient 3.x has the following code in its executeMethod() method:
1 2 3 4 5 6 7 8 9 | ... if (hostconfig == defaulthostconfig || uri.isAbsoluteURI()) { // make a deep copy of the host defaults hostconfig = (HostConfiguration) hostconfig.clone(); if (uri.isAbsoluteURI()) { hostconfig.setHost(uri); } } ... |
So, in my case (absolute URI) the modified host config (uses EasySSLProtocolSocketFactory) is cloned.
Problem: since the so called “deep copy” isn’t a proper deep copy the copy’s protocol’s socket factory is no longer EasySSLProtocolSocketFactory but the standard SSLProtocolSocketFactory instead!
Update
Apparently, this behavior is “well known and documented”. Since I couldn’t find anything in the HttpClient 3.x documentation I tried Google again and made note of the following JIRA issues and one particular mailing list entry:
- http://issues.apache.org/jira/browse/HTTPCLIENT-634
- http://issues.apache.org/jira/browse/HTTPCLIENT-683
- http://issues.apache.org/jira/browse/HTTPCLIENT-783
- http://www.mail-archive.com/httpclient-user@jakarta.apache.org/msg03530.html
Please note that HttpClient 4.x does not have this limitation!
I am using the same way , to accept the self signed certificates.
I have made sure that I pass a relative URI and use a new customized hostConfiguration object , instead of the HttpClients host configuration.
But still it is going inside the if condition and trying to clone:
if (hostconfig == defaulthostconfig || uri.isAbsoluteURI()) {
3 // make a deep copy of the host defaults
4 hostconfig = (HostConfiguration) hostconfig.clone();
5 if (uri.isAbsoluteURI()) {
6 hostconfig.setHost(uri);
7 }
8 }
Can you please help, or if you can point me from where can I download httpclient 4.x
your help will be really appreciated
Thanks in Advance
You don’t know from where to get 4.x? Have you tried Google…make an effort, dude. -> http://hc.apache.org/httpcomponents-client/index.html
As for your real problem, obviously one of hostconfig == defaulthostconfig or uri.isAbsoluteURI() apparently returns true. When you’re there with the debugger you should be able to find out. I really can’t tell from here.
Dude! This is excellent and saved a lot of my time.