How to create a pool of Apache HttpClients with different SSL client authentication certificates


Kerry Gunn:

I've been digging through the Apache documentation and other examples trying to create a client that uses Apache HttpClient to call various RESTful web services. (Each web service may require a different client certificate for authentication). Initially, I created a static block of code that initializes HttpClient (with SSLContext information and pooled connection manager):

private static CloseableHttpClient _client;
static {
  HttpClientBuilder clientBuilder = HttpClients.custom();
  SSLContextBuilder sslContextBuilder = SSLContexts.custom();
  sslContextBuilder.loadTrustMaterial(new TrustSelfSignedStrategy());
  sslContextBuilder.loadKeyMaterial(new File("clientcert.p12"), password, password, (aliases, socket) -> aliases.keySet().iterator().next());

  SSLContext sslContext = sslContextBuilder.build();
  HostnameVerifier allowAllHosts = new NoopHostnameVerifier();
  SSLConnectionSocketFactory connectionFactory = new SSLConnectionSocketFactory(sslContext, allowAllHosts);
  clientBuilder.setSSLSocketFactory(connectionFactory);

  RegistryBuilder<ConnectionSocketFactory> regBuilder = RegistryBuilder.<ConnectionSocketFactory>create();
  regBuilder.register("https", connectionFactory);
  regBuilder.register("http", new PlainConnectionSocketFactory());
  Registry<ConnectionSocketFactory> socketFactoryRegistry = regBuilder.build();

  PoolingHttpClientConnectionManager connectionManager = new PoolingHttpClientConnectionManager(socketFactoryRegistry);
  clientBuilder.setConnectionManager(connectionManager);
  _client = clientBuilder.build();
}

At this point, I can perform requests with the client, and client authentication works fine as long as the server is configured to allow access to clientcert.p12.

What I need is to be able to dynamically change the client certificate for each request based on the value of the required client certificate.

Can a static HttpClient be reused when changing client certificates dynamically? Also, if possible, would I still see a performance benefit of using a pooled connection manager?

ok2c :

There is an undocumented http.socket-factory-registryexecution context property that can be used to override the connection socket factory set by the connection manager at build time.

CloseableHttpClient httpClient = HttpClientBuilder.create()
        .setSSLContext(SSLContexts.createSystemDefault())
        .build();

SSLContext customSSlContext = SSLContexts.custom()
        .loadKeyMaterial(new File("my-keystore.jks"), "sectret".toCharArray(),  "sectret".toCharArray())
        .build();

Registry<ConnectionSocketFactory> socketFactoryRegistry = RegistryBuilder.<ConnectionSocketFactory>create()
        .register("http", PlainConnectionSocketFactory.getSocketFactory())
        .register("https", new SSLConnectionSocketFactory(customSSlContext))
        .build();

HttpClientContext clientContext = HttpClientContext.create();
clientContext.setAttribute("http.socket-factory-registry", socketFactoryRegistry);
try (CloseableHttpResponse response = httpClient.execute(new HttpGet("https://host/stuff"), clientContext)) {
    System.out.println(response.getStatusLine());
    EntityUtils.consume(response.getEntity());
}

Be careful when using multiple threads with different user identities/security contexts when executing requests using the same client instance/same connection pool.

Related


How to allow specific SSL client certificates in Nginx?

Joe White Nginx ssl_client_certificateand ssl_trusted_certificatedirectives can be used to allow client certificates signed by a given authority. But how to allow specific certificates? I want to filter by certificate thumbprint or by certificate authority + c

How to handle invalid SSL certificates with Apache HttpClient?

Rauch: I know, there are many different questions and many answers about this...but I don't get it... I have: installed ubuntu-9.10-desktop-amd64 + NetBeans6.7.1 "as is" from shutdown. Represents that I need to connect to a site via HTTPS. For this I use Apach

How to handle invalid SSL certificates with Apache HttpClient?

Rauch: I know, there are many different questions and many answers about this...but I don't get it... I have: installed ubuntu-9.10-desktop-amd64 + NetBeans6.7.1 "as is" from shutdown. Represents that I need to connect to a site via HTTPS. For this I use Apach

How to handle invalid SSL certificates with Apache HttpClient?

Rauch: I know, there are many different questions and many answers about this...but I don't get it... I have: installed ubuntu-9.10-desktop-amd64 + NetBeans6.7.1 "as is" from shutdown. Represents that I need to connect to a site via HTTPS. For this I use Apach

How to create SSL socket factory in new Apache Http Client 4.3?

expert How to create SSL socket factory in new Apache Http Client 4.3? This is how I created it before 4.3 val ts = new TrustStrategy() { def isTrusted(chain: Array[X509Certificate], authType: String): Boolean = true } new SSLSocketFactory(ts, SSLSocketFact

How to create SSL socket factory in new Apache Http Client 4.3?

expert How to create SSL socket factory in new Apache Http Client 4.3? This is how I created it before 4.3 val ts = new TrustStrategy() { def isTrusted(chain: Array[X509Certificate], authType: String): Boolean = true } new SSLSocketFactory(ts, SSLSocketFact

How to create SSL socket factory in new Apache Http Client 4.3?

expert How to create SSL socket factory in new Apache Http Client 4.3? This is how I created it before 4.3 val ts = new TrustStrategy() { def isTrusted(chain: Array[X509Certificate], authType: String): Boolean = true } new SSLSocketFactory(ts, SSLSocketFact

How to create SSL socket factory in new Apache Http Client 4.3?

expert How to create SSL socket factory in new Apache Http Client 4.3? This is how I created it before 4.3 val ts = new TrustStrategy() { def isTrusted(chain: Array[X509Certificate], authType: String): Boolean = true } new SSLSocketFactory(ts, SSLSocketFact

SSL certificates in different ports

Azamat Hi! My problem: I am using a web application with an SSL certificate in port 443 and this application has a web service in javascript. The web service connects on a different port 7443 and uses the same certificate. But the certificate is not added to p

Why Certificates Are Not Secrets for SSL Authentication

qweruiop I'm reading about certificate based authentication in SSL and have a question about the process. (Picture was taken from the link above) The question is: why server.cerand client.cernot a secret. In this diagram, it appears that the communication is n

Why Certificates Are Not Secrets for SSL Authentication

qweruiop I'm reading about certificate based authentication in SSL and have a question about the process. (Picture was taken from the link above) The question is: why server.cerand client.cernot a secret. In this diagram, it appears that the communication is n

WSDL client authentication and multiple certificates

other: So I'm having issues with wsdls here, with multiple certificates selected in Java. For example, a smart card has multiple certificates on it for signing, encryption and identification. I have a WSDL that generates code for client auth connections, but a

WSDL client authentication and multiple certificates

other: So I'm having issues with wsdls here, with multiple certificates selected in Java. For example, a smart card has multiple certificates on it for signing, encryption and identification. I have a WSDL that generates code for client auth connections, but a

WSDL client authentication and multiple certificates

other: So I'm having issues with wsdls here, with multiple certificates selected in Java. For example, a smart card has multiple certificates on it for signing, encryption and identification. I have a WSDL that generates code for client auth connections, but a

How secure are client-side SSL certificates in mobile apps?

Jacob Marble I want to have secure communication between my Android/iOS app and my internet access backend service, so I'm looking into HTTPS/SSL. If I create a self-signed certificate, then put the client certificate into the application, and have the backend