Monday, January 11, 2010

Peer Unverified Exception accessing secure web sites with HttpClient

When trying to access to secure web sites (https protocol) using apache HttpClient library, sometimes you can get the following error:


javax.net.ssl.SSLPeerUnverifiedException: peer not authenticated
at sun.security.ssl.SSLSessionImpl.getPeerCertificates(SSLSessionImpl.java:371)
at org.apache.http.conn.ssl.AbstractVerifier.verify(AbstractVerifier.java:129)
at org.apache.http.conn.ssl.SSLSocketFactory.connectSocket(SSLSocketFactory.java:326)
at org.apache.http.impl.conn.DefaultClientConnectionOperator.openConnection(DefaultClientConnectionOperator.java:129)
at org.apache.http.impl.conn.AbstractPoolEntry.open(AbstractPoolEntry.java:164)
at org.apache.http.impl.conn.AbstractPooledConnAdapter.open(AbstractPooledConnAdapter.java:119)
at org.apache.http.impl.client.DefaultRequestDirector.execute(DefaultRequestDirector.java:349)
at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:555)
at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:487)
at org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:465)


This exception occurs when page is sending a non trusted certificate. So, the solution to this exception is to import the certificate into your trusted certificates database.
  • Step 1. Export web page authenticate.
Use a browser to access the web site you want to access with HttpClient. Go to "privacity->certificates" options in the browser and export it to a ".cert" file
  • Step 2. Create truststore file.
Import the ".cert" file in a truststore database. Use the following command:
keytool -import -v -trustcacerts -alias certAlias -keypass changeme -file thefile.cert -keystore truststore -storepass changeme
  • Step 3. Copy "truststore" file to your project.
  • Step 4. Add the following code (in Groovy):
def keyStore = java.security.KeyStore.getInstance( KeyStore.defaultType )

def store =getClass().getResourceAsStream( "/cert/truststore" )
keyStore.load( store, "thepassword".toCharArray() )
client.connectionManager.schemeRegistry.register(
new Scheme("https", new SSLSocketFactory(keyStore), 443) )

Where "client" is the HttpClient instance.

  • IMPROTANT NOTE. "truststore" file mus be generated with JKS format. OpenJDK uses GKR format by default wich is not compatible. Sun JDK uses JKS format by default.