Apache HttpClient - Custom SSL Context


Advertisements

Using Secure Socket Layer, you can establish a secured connection between the client and server. It helps to safeguard sensitive information such as credit card numbers, usernames, passwords, pins, etc.

You can make connections more secure by creating your own SSL context using the HttpClient library.

Follow the steps given below to customize SSLContext using HttpClient library −

Step 1 - Create SSLContextBuilder object

SSLContextBuilder is the builder for the SSLContext objects. Create its object using the custom() method of the SSLContexts class.

//Creating SSLContextBuilder object
SSLContextBuilder SSLBuilder = SSLContexts.custom();

Step 2 - Load the Keystore

In the path Java_home_directory/jre/lib/security/, you can find a file named cacerts. Save this as your key store file (with extension .jks). Load the keystore file and, its password (which is changeit by default) using the loadTrustMaterial() method of the SSLContextBuilder class.

//Loading the Keystore file
File file = new File("mykeystore.jks");
SSLBuilder = SSLBuilder.loadTrustMaterial(file, "changeit".toCharArray());

Step 3 - build an SSLContext object

An SSLContext object represents a secure socket protocol implementation. Build an SSLContext using the build() method.

//Building the SSLContext
SSLContext sslContext = SSLBuilder.build();

Step 4 - Creating SSLConnectionSocketFactory object

SSLConnectionSocketFactory is a layered socket factory for TSL and SSL connections. Using this, you can verify the Https server using a list of trusted certificates and authenticate the given Https server.

You can create this in many ways. Depending on the way you create an SSLConnectionSocketFactory object, you can allow all hosts, allow only self-signed certificates, allow only particular protocols, etc.

To allow only particular protocols, create SSLConnectionSocketFactory object by passing an SSLContext object, string array representing the protocols need to be supported, string array representing the cipher suits need to be supported and a HostnameVerifier object to its constructor.

new SSLConnectionSocketFactory(sslcontext, new String[]{"TLSv1"}, null,    
   SSLConnectionSocketFactory.getDefaultHostnameVerifier());

To allow all hosts, create SSLConnectionSocketFactory object by passing a SSLContext object and a NoopHostnameVerifier object.

//Creating SSLConnectionSocketFactory SSLConnectionSocketFactory object
SSLConnectionSocketFactory sslConSocFactory = new SSLConnectionSocketFactory(sslcontext, new NoopHostnameVerifier());

Step 5 - Create an HttpClientBuilder object

Create an HttpClientBuilder object using the custom() method of the HttpClients class.

//Creating HttpClientBuilder
HttpClientBuilder clientbuilder = HttpClients.custom();

Step 6 - Set the SSLConnectionSocketFactory object

Set the SSLConnectionSocketFactory object to the HttpClientBuilder using the setSSLSocketFactory() method.

//Setting the SSLConnectionSocketFactory
clientbuilder = clientbuilder.setSSLSocketFactory(sslConSocFactory);

Step 7 - Build the CloseableHttpClient object

Build the CloseableHttpClient object by calling the build() method.

//Building the CloseableHttpClient
CloseableHttpClient httpclient = clientbuilder.build();

Step 8 - Create an HttpGet object

The HttpGet class represents the HTTP GET request which retrieves the information of the given server using a URI.

Create a HTTP GET request by instantiating the HttpGet class by passing a string representing the URI.

//Creating the HttpGet request
HttpGet httpget = new HttpGet("https://example.com/");

Step 9 - Execute the request

Execute the request using the execute() method.

//Executing the request
HttpResponse httpresponse = httpclient.execute(httpget);

Example

Following example demonstrates the customization of the SSLContrext −

import java.io.File;
import javax.net.ssl.SSLContext;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.conn.ssl.NoopHostnameVerifier;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.ssl.SSLContextBuilder;
import org.apache.http.ssl.SSLContexts;
import org.apache.http.util.EntityUtils;

public class ClientCustomSSL {
   
   public final static void main(String[] args) throws Exception {

      //Creating SSLContextBuilder object
      SSLContextBuilder SSLBuilder = SSLContexts.custom();
  
      //Loading the Keystore file
      File file = new File("mykeystore.jks");
      SSLBuilder = SSLBuilder.loadTrustMaterial(file,
         "changeit".toCharArray());

      //Building the SSLContext usiong the build() method
      SSLContext sslcontext = SSLBuilder.build();
 
      //Creating SSLConnectionSocketFactory object
      SSLConnectionSocketFactory sslConSocFactory = new SSLConnectionSocketFactory(sslcontext, new NoopHostnameVerifier());
 
      //Creating HttpClientBuilder
      HttpClientBuilder clientbuilder = HttpClients.custom();

      //Setting the SSLConnectionSocketFactory
      clientbuilder = clientbuilder.setSSLSocketFactory(sslConSocFactory);

      //Building the CloseableHttpClient
      CloseableHttpClient httpclient = clientbuilder.build();
      
      //Creating the HttpGet request
      HttpGet httpget = new HttpGet("https://example.com/");
 
      //Executing the request
      HttpResponse httpresponse = httpclient.execute(httpget);

      //printing the status line
      System.out.println(httpresponse.getStatusLine());

      //Retrieving the HttpEntity and displaying the no.of bytes read
      HttpEntity entity = httpresponse.getEntity();
      if (entity != null) {
         System.out.println(EntityUtils.toByteArray(entity).length);
      } 
   }
}

Output

On executing, the above program generates the following output.

HTTP/1.1 200 OK
1270
Advertisements