Self signed certificates in Apache HttpClient

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:

...
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

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:

...
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:

Please note that HttpClient 4.x does not have this limitation!

 

 

3 thoughts on “Self signed certificates in Apache HttpClient

  1. 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

Leave a Reply