DZone
Thanks for visiting DZone today,
Edit Profile
  • Manage Email Subscriptions
  • How to Post to DZone
  • Article Submission Guidelines
Sign Out View Profile
  • Post an Article
  • Manage My Drafts
Newsletter
Log In / Join
Refcards Trend Reports
Events Video Library
Refcards
Trend Reports

Events

View Events Video Library

Related

  • Securing AI/ML Workloads in the Cloud: Integrating DevSecOps with MLOps
  • Five Nonprofit & Charity APIs That Make Due Diligence Way Less Painful for Developers
  • API Analytics: Unleashing the Power of Data-Driven Insights for Enhanced API Management
  • What’s the Future of Device Management? 5 Predictions For What Lies Ahead

Trending

  • Fix the Target, Precompute Once: A Backend-Free Word-Ladder Solver With a BFS Distance Field
  • Integrating Apache Spark With Drools: A Loan Approval Demo
  • The Permission Was Valid. The Action Was Not Authorized.
  • Should Developers Switch From SQLite to DuckDB?

Draft This article hasn't been published, so readers can't see it.

In moderation This article is waiting for review, so readers can't see it yet.

Deleted This article has been deleted, so readers can't see it.

  1. DZone
  2. Software Design and Architecture
  3. Security
  4. Apache HTTP Client:  Client-Side SSL Certificate

Apache HTTP Client:  Client-Side SSL Certificate

Need help working with your Apache HTTP Client?

By 
Simone Pezzano
·
Mar. 25, 19 · Tutorial
Post on X (opens in a new tab) Share on LinkedIn (opens in a new tab)
52.4K Views

Join the DZone community Save articles, join the discussion, and download Refcards and Trend Reports with a free account.

Join for free Already a member? Log in

I’m sharing this snippet with you because it’s been a little tricky to work with, so I hope that I can save you some time.

Note: I’m referring to Apache HTTP Client 4.3. You know its API is pretty lively, so before you dive into it, make sure it applies to the version you’re using as well.

Background

Creating an HTTP connection using Apache HTTP Client is pretty straight forward, and this is why we love it. Fine tuning how the client works is essential in production environments, and it does require a little bit of tweaking, but the results are excellent.

It’s not a surprise that client-side SSL certificates (also known as two-way SSL or mutual SSL authentication) is doable, but of course, being something that interferes with the intimate nature of the HTTP conversation, the process isn’t exactly straight forward.

If you’re unaware of this security practice, here’s the shortest possible summary: to provide stricter security for HTTPS connections involving very selected parties, you can let them have an SSL client certificate that will identify them. The SSL dance will not work if the server and client certificates are not a match. By doing so, no credential is sent over the Internet, just encrypted data that will be decrypted correctly only if the certificates match.

If you want to know more, here’s a useful article by Robin Howlett.

Practice

Incomplete chains, root certificates that need to be updated, etc. — certificates are a pain already. So, you would assume that this is a piece of cake, right?

First off, let’s be clear about the fact that you are not going to configure this for a specific connection. The HTTP Client instance needs to be built around the fact that it will support that certificate.

First, let’s create a keystore:

KeyStore ks = KeyStore.getInstance(KeyStore.getDefaultType());


The factory will create a JKS keystore by default. You can alter which one you will get by changing the parameter. For example, PKCS12 is an option. I’m sticking with JKS for this example. This implies that you already created a keystore and added the certificate to it.

Secondly, we load the keystore:

ks.load(inputStream,"password")


Any inputStream will do. We need to provide a password to decode the keystore, of course.

SSLContext sslContext = SSLContexts.custom()
                                .loadKeyMaterial(ks, "password".toCharArray())
                                .loadTrustMaterial(null, new TrustSelfSignedStrategy())
                                .build();


We basically create a custom SSL Context, load the keystore, and load the trust store (the null parameter will default to the cacerts file).

SSLConnectionSocketFactory sslConnectionFactory =
                                new SSLConnectionSocketFactory(sslContext, SSLConnectionSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);


We create a socket connection factory providing the SSL context. The hostname verifier is literally up to you, and it pretty much depends on the service you will be interactive with. The  ALLOW_ALL_HOSTNAME_VERIFIER is loose, so you might want to consider moving it to “strict” if the server allows you to.

Registry<ConnectionSocketFactory> registry = RegistryBuilder.<ConnectionSocketFactory>create()
                                                        .register("https", sslConnectionFactory)
                                                        .register("http", new PlainConnectionSocketFactory())
                                                        .build();


This registry associates what socket factory to use based on the protocol.

BasicHttpClientConnectionManager connManager = BasicHttpClientConnectionManager(registry);


We instantiate a connection manager that will use the registry. We’re using the basic connection manager here because it’s simpler for the example. Connection managers are a vital part of tuning HTTP client, so make sure you’re using something that suits your use case.

HttpClient client = HttpClients.custom()
                                .setConnectionManager(connManager)
                                .setSSLSocketFactory(sslConnectionFactory)
                          .setHostnameVerifier(SSLConnectionSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER)
                          .build();


We finally instantiate our HTTP client that will eventually be successful when talking to our highly secure peer. As we mentioned previously, the hostname verifier has to be edited based on your needs.
Note: this example contains only the strictly necessary commands to make it work. A lot of other configuration options may be needed in your context.

And we should be set to go.

Let me repeat one important point: before you dive into this practice, make sure it suits your HTTP Client version. Various refactoring and changes in the API may strongly impact the way to do it.

Hope this helps! Take care.

Connection (dance) Factory (object-oriented programming) IT security API Snippet (programming) Trust (business) Data (computing) Production (computer science)

Published at DZone with permission of Simone Pezzano. See the original article here.

Opinions expressed by DZone contributors are their own.

Related

  • Securing AI/ML Workloads in the Cloud: Integrating DevSecOps with MLOps
  • Five Nonprofit & Charity APIs That Make Due Diligence Way Less Painful for Developers
  • API Analytics: Unleashing the Power of Data-Driven Insights for Enhanced API Management
  • What’s the Future of Device Management? 5 Predictions For What Lies Ahead

Partner Resources

×

Comments

Loading comments

The comments didn't load

Please try again in a moment.

Likes

Loading

The next likes didn't load. Please try again.

The likes didn't load

Please try again in a moment.

See who liked this

Log in or join DZone for free to see who liked this article.

Log in Join for free
  • RSS
  • X
  • Facebook

ABOUT US

  • About DZone
  • Support and feedback
  • Community research

ADVERTISE

  • Advertise with DZone

CONTRIBUTE ON DZONE

  • Article Submission Guidelines
  • Become a Contributor
  • Core Program
  • Visit the Writers' Zone

LEGAL

  • Terms of Service
  • Privacy Policy

CONTACT US

  • 3343 Perimeter Hill Drive
  • Suite 215
  • Nashville, TN 37211
  • [email protected]

Let's be friends:

  • RSS
  • X
  • Facebook