Friday, June 15, 2012

Simplest Jetty HttpClient to work in HTTPS

Took me a while to find out how to make HttpClient in Jetty works over Https - The problem is that Jetty HttpClient does not maintain the session nor the cookies for you, and you have to set it manually after being authenticated at the first place.

Here is a simple example to illustrate it:



package Testing;

import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

import org.eclipse.jetty.client.ContentExchange;
import org.eclipse.jetty.client.HttpClient;
import org.eclipse.jetty.client.HttpExchange;
import org.eclipse.jetty.io.Buffer;



public class JettyHttpClientCookieTest {
    public final static void main(String[] args) throws Exception {
        String loginUri = new String("https://10.176.40.10:8443/admin?op=login&username=<username>&password=<password>");
        String setGroupUri = new String("https://10.176.40.10:8443/admin?op=setGroup&groupId=1");

        if (httpClient == null) {
            httpClient = new HttpClient(); 
        }
     httpClient.setConnectorType(HttpClient.CONNECTOR_SELECT_CHANNEL);  
     try {
         System.out.println("Start the Http client...");
         httpClient.start();    
         
         System.out.println("Login to CMS ...");
         ContentExchange exchange = new ContentExchange(true) {
             protected void onResponseHeader(Buffer name, Buffer value) throws IOException {
                 System.out.println("Buffer name: " + name.toString() + "; Buffer value: " + value.toString());
                 if (name.toString().equals("Set-Cookie")) {
                     cookies.add(value.toString());
                 }
            }
         };
         exchange.setMethod("POST");
         exchange.setURL(loginUri);
      
         httpClient.send(exchange);
         if (exchange.waitForDone() == ContentExchange.STATUS_COMPLETED) {
             System.out.println("ContentExchange content: " + exchange.getResponseContent());
         }
            
         System.out.println("Set the group");
         ContentExchange exchange2 = new ContentExchange(true);
         exchange2.setMethod("POST");
         exchange2.setURL(setGroupUri);
         for (String cookie: cookies) {
             exchange2.setRequestHeader("Cookie", cookie);
         }
         httpClient.send(exchange2);
         if (exchange2.waitForDone() == ContentExchange.STATUS_COMPLETED) {
             System.out.println("ContentExchange content: " + exchange2.getResponseContent());
         }
        
         System.out.println("Fetch Shefl...");
         ContentExchange exchange3 = new ContentExchange(true);
         String fetchShelfUri = new String("https://10.176.40.10:8443/fetch?shelf");
         exchange3.setMethod("GET");
         exchange3.setURL(fetchShelfUri);
         for (String cookie: cookies) {
             exchange3.setRequestHeader("Cookie", cookie);
         }
         httpClient.send(exchange3);
         if (exchange3.waitForDone() == ContentExchange.STATUS_COMPLETED) {
             System.out.println("ContentExchange content: " + exchange3.getResponseContent());
         }
         
         System.out.println("Done");
     }
     catch (Exception e) {
         return;
     }
    }
    
    public static class JettyHttpExchangeExt extends HttpExchange {
        // Examine the response header
        protected void onResponseHeader(Buffer name, Buffer value) throws IOException {
             System.out.println("Buffer name: " + name.toString() + "; Buffer value: " + value.toString());
        }
    }

    public static List<String> cookies = new ArrayList<String>();
    public static HttpClient httpClient = null;
}

Simplest Apache HttpClient to test HTTPS connection


package Testing;

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;

import org.apache.http.Header;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.conn.scheme.Scheme;
import org.apache.http.conn.ssl.SSLSocketFactory;
import org.apache.http.conn.ssl.TrustStrategy;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.util.EntityUtils;

/**
 * This example demonstrates how to create secure connections with a custom SSL
 * context.
 */
public class ClientCustomSSL {

    public final static void main(String[] args) throws Exception {
        DefaultHttpClient httpclient = new DefaultHttpClient();
        try {
            /* Uncomment the below line and proceed with the cert if you have one.
            KeyStore trustStore  = KeyStore.getInstance(KeyStore.getDefaultType());
            FileInputStream instream = new FileInputStream(new File("<my_keystore>"));
            try {
                trustStore.load(instream, "<mypassword to decode my_keystore>".toCharArray());
            } finally {
                try { instream.close(); } catch (Exception ignore) {}
            }
  
            SSLSocketFactory socketFactory = new SSLSocketFactory(trustStore);
             */
            SSLSocketFactory socketFactory = new SSLSocketFactory( new TrustStrategy() {
                // This function below make the session always "trusted" without using the above trustStore.
                public boolean isTrusted(final X509Certificate[] chain, String authType) throws CertificateException {
                    return true;
                }
            }, org.apache.http.conn.ssl.SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);

            Scheme sch = new Scheme("https", 8443, socketFactory);
            httpclient.getConnectionManager().getSchemeRegistry().register(sch);
            HttpPost httppost = new HttpPost("https://10.176.40.10:8443/admin?op=login&username=admin&password=AdminAdmin");
            
            Header headers[] = httppost.getAllHeaders();      
            HttpResponse response = httpclient.execute(httppost);
            HttpEntity entity = response.getEntity();
            headers = response.getAllHeaders();

            System.out.println("----------------------------------------");
            
            System.out.println(response.getStatusLine());
            if (entity != null) {
                System.out.println("Response content length: " + entity.getContentLength());
                BufferedReader br = new BufferedReader(
                        new InputStreamReader((response.getEntity().getContent())));

                String output;
                System.out.println("Output from Server .... \n");
                while ((output = br.readLine()) != null) {
                    System.out.println(output);
                }
                for(Header h:headers){
                    System.out.println(h.getName() + ": " + h.getValue());
                }
              
                // Now do another post to see that the authenticated session persists - no cookie need to send along.
                httppost = new HttpPost("https://10.176.40.10:8443/admin?op=setRbacGroup&groupId=1");
                response = httpclient.execute(httppost);
                entity = response.getEntity();
                headers = response.getAllHeaders();
                System.out.println("Output from Server .... \n");
                br = new BufferedReader(
                        new InputStreamReader((response.getEntity().getContent())));
                while ((output = br.readLine()) != null) {
                    System.out.println(output);
                }             
                // Now do a get to see that the authenticated session persists - no cookie need to send along.
                HttpGet httpget = new HttpGet("https://10.176.40.10:8443/fetch?shelf");
                response = httpclient.execute(httpget);
                entity = response.getEntity();
                headers = response.getAllHeaders();
                System.out.println("Output from Server .... \n");
                br = new BufferedReader(
                        new InputStreamReader((response.getEntity().getContent())));
                while ((output = br.readLine()) != null) {
                    System.out.println(output);
                }
            } 
            EntityUtils.consume(entity);

        } finally {
            // When HttpClient instance is no longer needed,
            // shut down the connection manager to ensure
            // immediate deallocation of all system resources
            httpclient.getConnectionManager().shutdown();
        }
    }
    

}