JavaExample.net | Bypass self-signed certificate on httpclient

When we execute an https connection with a server http that utilize a self-signed certificate we can obtain following exeption:

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
at sun.security.ssl.Alerts.getSSLException(Alerts.java:192)
at sun.security.ssl.SSLSocketImpl.fatal(SSLSocketImpl.java:1697)
at sun.security.ssl.Handshaker.fatalSE(Handshaker.java:258)
at sun.security.ssl.Handshaker.fatalSE(Handshaker.java:252)
at sun.security.ssl.ClientHandshaker.serverCertificate(ClientHandshaker.java:1165)
at sun.security.ssl.ClientHandshaker.processMessage(ClientHandshaker.java:154)
at sun.security.ssl.Handshaker.processLoop(Handshaker.java:610)
at sun.security.ssl.Handshaker.process_record(Handshaker.java:546)
at sun.security.ssl.SSLSocketImpl.readRecord(SSLSocketImpl.java:945)
at sun.security.ssl.SSLSocketImpl.performInitialHandshake(SSLSocketImpl.java:1190)
at sun.security.ssl.SSLSocketImpl.writeRecord(SSLSocketImpl.java:657)
at sun.security.ssl.AppOutputStream.write(AppOutputStream.java:107)
at java.io.BufferedOutputStream.flushBuffer(BufferedOutputStream.java:82)
at java.io.BufferedOutputStream.flush(BufferedOutputStream.java:140)
at org.apache.commons.httpclient.methods.EntityEnclosingMethod.writeRequestBody(EntityEnclosingMethod.java:502)
at org.apache.commons.httpclient.HttpMethodBase.writeRequest(HttpMethodBase.java:1973)
at org.apache.commons.httpclient.HttpMethodBase.execute(HttpMethodBase.java:993)
at org.apache.commons.httpclient.HttpMethodDirector.executeWithRetry(HttpMethodDirector.java:397)
at org.apache.commons.httpclient.HttpMethodDirector.executeMethod(HttpMethodDirector.java:170)
at org.apache.commons.httpclient.HttpClient.executeMethod(HttpClient.java:396)
at org.apache.commons.httpclient.HttpClient.executeMethod(HttpClient.java:324)

 

To resolve this issue we can following two way:

  1. install the certificate in our machine and java cacert with keytool
  2. bypass self-signed certificate through java code
We are using the second way, so we write an httpClient based on apache HTTPClient 3.x and we implement a MySSLSocketFactory that implements org.apache.commons.httpclient.protocol.ProtocolSocketFactory
Well our http client is

package net.javaexample.base;
 
import java.io.ByteArrayInputStream;
import net.javaexample.base.ssl.MySSLSocketFactory;
import org.apache.commons.httpclient.HttpClient;
import org.apache.commons.httpclient.methods.InputStreamRequestEntity;
import org.apache.commons.httpclient.methods.PostMethod;
import org.apache.commons.httpclient.protocol.Protocol;
 
public class ClientHttp
{
    private HttpClient httpClient;
    private String     serverHost;
    private boolean    acceptSelfSignedSsl = true;
 
    /**
     * @param serverHost
     *            nella forma http://localhost:8080
     */
    public ClientHttp(String serverHost)
    {
        super();
        this.serverHost = serverHost;
    }
 
    private void init()
    {
        if (httpClient == null)
            httpClient = new HttpClient();
        if (acceptSelfSignedSsl)
        {
            Protocol.registerProtocol("https", new Protocol("https", new MySSLSocketFactory(), 443));
        }
    }
 
    public String sendPostCommand(String xml)
    {
        String response = null;
        init();
        PostMethod post = new PostMethod(serverHost);
        try
        {
            byte[] xmlBytes = xml.getBytes("UTF-8");
            post.setRequestEntity(new InputStreamRequestEntity(new ByteArrayInputStream(xmlBytes), xmlBytes.length));
            // Specify content type and encoding
            post.setRequestHeader("Content-type", "text/xml; charset=UTF-8");
            int result = httpClient.executeMethod(post);
            String xmlResponse = post.getResponseBodyAsString();
            System.out.println("HTTP RESULT:" + result);
            System.out.println("XML response:" + xmlResponse);
        }
        catch (Throwable t)
        {
            t.printStackTrace();
 
        }
        finally
        {
            // Release current connection to the connection pool
            // once you are done
            post.releaseConnection();
        }
        return response;
    }
 
    public boolean isAcceptSelfSignedSsl()
    {
        return acceptSelfSignedSsl;
    }
 
    public void setAcceptSelfSignedSsl(boolean acceptSelfSignedSsl)
    {
        this.acceptSelfSignedSsl = acceptSelfSignedSsl;
    }
 
    public static void main(String[] args)
    {
        ClientHttp client = new ClientHttp("https://localhost");
        String xmlOut = client.sendPostCommand("test");
        System.out.println(xmlOut);
    }
}
 

and MySSLSocketFactory to bypass self-signed certificate is

package net.javaexample.base.ssl;
 
import java.io.IOException;
import java.net.InetAddress;
import java.net.Socket;
import java.net.UnknownHostException;
import javax.net.SocketFactory;
import javax.net.ssl.HttpsURLConnection;
import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManager;
import javax.net.ssl.X509TrustManager;
import org.apache.commons.httpclient.ConnectTimeoutException;
import org.apache.commons.httpclient.params.HttpConnectionParams;
import org.apache.commons.httpclient.protocol.ProtocolSocketFactory;
 
 
/**
 * to bypass self-signed certificate
 * 
 *
 */
public class MySSLSocketFactory implements ProtocolSocketFactory {
 
	private TrustManager[] getTrustManager() {
 
		TrustManager[] trustAllCerts = new TrustManager[] {
 
		new X509TrustManager() {
 
			public java.security.cert.X509Certificate[] getAcceptedIssuers() {
 
				return null;
 
			}
 
			public void checkClientTrusted(
 
			java.security.cert.X509Certificate[] certs, String authType) {
 
			}
 
			public void checkServerTrusted(
 
			java.security.cert.X509Certificate[] certs, String authType) {
 
			}
 
		}
 
		};
 
		return trustAllCerts;
 
	}
 
	public Socket createSocket(String host, int port) throws IOException,
			UnknownHostException {
 
		TrustManager[] trustAllCerts = getTrustManager();
 
		try {
 
			SSLContext sc = SSLContext.getInstance("SSL");
 
			sc.init(null, trustAllCerts, new java.security.SecureRandom());
 
			HttpsURLConnection
					.setDefaultSSLSocketFactory(sc.getSocketFactory());
 
			SocketFactory socketFactory = HttpsURLConnection
					.getDefaultSSLSocketFactory();
 
			return socketFactory.createSocket(host, port);
 
		}
 
		catch (Exception ex) {
 
			throw new UnknownHostException("Problems to connect " + host
					+ ex.toString());
 
		}
 
	}
 
	public Socket createSocket(Socket socket, String host, int port,
			boolean flag) throws IOException, UnknownHostException {
 
		TrustManager[] trustAllCerts = getTrustManager();
 
		try {
 
			SSLContext sc = SSLContext.getInstance("SSL");
 
			sc.init(null, trustAllCerts, new java.security.SecureRandom());
 
			HttpsURLConnection
					.setDefaultSSLSocketFactory(sc.getSocketFactory());
 
			SocketFactory socketFactory = HttpsURLConnection
					.getDefaultSSLSocketFactory();
 
			return socketFactory.createSocket(host, port);
 
		}
 
		catch (Exception ex) {
 
			throw new UnknownHostException("Problems to connect " + host
					+ ex.toString());
 
		}
 
	}
 
	public Socket createSocket(String host, int port, InetAddress clientHost,
			int clientPort) throws IOException, UnknownHostException {
 
		TrustManager[] trustAllCerts = getTrustManager();
 
		try {
 
			SSLContext sc = SSLContext.getInstance("SSL");
 
			sc.init(null, trustAllCerts, new java.security.SecureRandom());
 
			HttpsURLConnection
					.setDefaultSSLSocketFactory(sc.getSocketFactory());
 
			SocketFactory socketFactory = HttpsURLConnection
					.getDefaultSSLSocketFactory();
 
			return socketFactory.createSocket(host, port, clientHost,
					clientPort);
 
		}
 
		catch (Exception ex) {
 
			throw new UnknownHostException("Problems to connect " + host
					+ ex.toString());
 
		}
 
	}
 
	@Override
	public Socket createSocket(String host, int port, InetAddress localAddress,
			int localPort, HttpConnectionParams arg4) throws IOException,
			UnknownHostException, ConnectTimeoutException {
		TrustManager[] trustAllCerts = getTrustManager();
 
		try {
 
			SSLContext sc = SSLContext.getInstance("SSL");
 
			sc.init(null, trustAllCerts, new java.security.SecureRandom());
 
			HttpsURLConnection
					.setDefaultSSLSocketFactory(sc.getSocketFactory());
 
			SocketFactory socketFactory = HttpsURLConnection
					.getDefaultSSLSocketFactory();
 
			return socketFactory.createSocket(host, port);
 
		}
 
		catch (Exception ex) {
 
			throw new UnknownHostException("Problems to connect " + host
					+ ex.toString());
 
		}
 
	}
 
}

Well It’s all!

Share →

Leave a Reply

Your email address will not be published. Required fields are marked *