SSL(TLS) Authentication:Web Services and Java

In this article we will talk about the SSL(TLS) authentication implementation as required when say calling a web serivce or making an HTTP get call using Java. SSL authentication can be either one way or mutual - where both consumer and provider must authenticate themselves. Lets first start with consumer of a web service. For a web service consumer, there are two major entities that you will be working with The Service endpoint interface(port) and the Service class itself. Lets look at how you obtain the port

This method will return you the port of the service you are trying to consume when the address is provided

JaxWsProxyFactoryBean beanFactory = new JaxWsProxyFactoryBean();
beanFactory.setServiceClass(KtipServiceSoap.class);
beanFactory.setAddress("http://localhost:port/KtipService/xxxx");
return (KtipServiceSoap)beanFactory.create();

Listing I

The SSL authenticaion parameters are passed in through the org.apache.cxf.transport.http.HTTPConduit. (Please note instead of passing SSL parameters through the configuration file, we are passing in through the code ). To get the conduit we must first get the org.apache.cxf.endpoint.Client fromthe port we just obtained. This is done as shown in Listing II.

KtipServiceSoap port = ...// obtained using the code from Listing I
org.apache.cxf.endpoint.Client client = ClientProxy.getClient(port);
HTTPConduit conduit = (HTTPConduit)client.getConduit();
conduit.setTlsClientParameters(fillTLSParameters());

Listing II

Now we will look at how we actually set the TLS parameters for the conduit. We can call a method that will populate the required parameters. The method will look as shown below in Listing III.

org.apache.cxf.configuration.jsse.TLSClientParameters tlsParams = new TLSClientParameters();
tlsParams.setSecureSocketProtocol("SSL");
tlsParams.setDisableCNCheck(true);
KeyStore keyStore;
    
// Add trust managers (to authenticate the service)
keyStore = KeyStore.getInstance("JKS");
keyStore.load(new FileInputStream(new File("jks file location")), new String("password").toCharArray());
TrustManagerFactory trustFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
trustFactory.init(keyStore);
TrustManager[] trustMgr = trustFactory.getTrustManagers();
tlsParams.setTrustManagers(trustMgr);
         
// Add key managers (to authenticate the client)
keyStore = KeyStore.getInstance("PKCS12");
keyStore.load(new FileInputStream(new File("pfx file location")), new String("password").toCharArray());
KeyManagerFactory keyFactory = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
keyFactory.init(keyStore, new String("customerInfoSys").toCharArray());
KeyManager[] keyMgr = keyFactory.getKeyManagers();
tlsParams.setKeyManagers(keyMgr);

FiltersType filter = new FiltersType();
filter.getInclude().add(".*_EXPORT_.*");
filter.getInclude().add(".*_EXPORT1024_.*");
filter.getInclude().add(".*_WITH_DES_.*");
filter.getInclude().add(".*_WITH_NULL_.*");
filter.getExclude().add(".*_DH_anon_.*");
tlsParams.setCipherSuitesFilter(filter);
return tlsParams;

Listing III

So when you build your consumer, you should be provided .jks and .pfx files (and passwords for each) for mutual authentication. If there is only one way authentication to be performed by the service only and not the client, this would be done as shown in Listing IV.

org.apache.cxf.configuration.jsse.TLSClientParameters tlsParams = new TLSClientParameters();
tlsParams.setSecureSocketProtocol("SSL");
tlsParams.setDisableCNCheck(true);
KeyStore keyStore;
    
// Add trust managers (to authenticate the client)
keyStore = KeyStore.getInstance("PKCS12");
keyStore.load(new FileInputStream(new File("pfx file location")), new String("password").toCharArray());
TrustManagerFactory trustFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
trustFactory.init(keyStore);
TrustManager[] trustMgr = trustFactory.getTrustManagers();
tlsParams.setTrustManagers(trustMgr);

FiltersType filter = new FiltersType();
filter.getInclude().add(".*_EXPORT_.*");
filter.getInclude().add(".*_EXPORT1024_.*");
filter.getInclude().add(".*_WITH_DES_.*");
filter.getInclude().add(".*_WITH_NULL_.*");
filter.getExclude().add(".*_DH_anon_.*");
tlsParams.setCipherSuitesFilter(filter);
return tlsParams;
    
Listing IV

In this part I will show how to write a simple Java method to make a HTTP GET/POST when the caller has to be authenticated

String getHTMLData(String address) throws Exception{
    String response = null;
    URLConnection connection =  new URL(address).openConnection();
    HttpsURLConnection sslConnection = null;
    HttpURLConnection nonsslConnection = null;
        
    if(connection instanceof HttpsURLConnection){
        sslConnection = (HttpsURLConnection)connection;
        sslConnection.setSSLSocketFactory(createSocketFactory());
        sslConnection.setRequestMethod("GET");
        if(sslConnection.getResponseCode() == HttpsURLConnection.HTTP_INTERNAL_ERROR ){
            throw new AdServerException("Problem calling ad server...");
        }
    }else if(connection instanceof HttpURLConnection){
        nonsslConnection = (HttpURLConnection)connection;
        nonsslConnection.setRequestMethod("GET");
    }
        
    BufferedReader rd = new BufferedReader(new InputStreamReader(connection.getInputStream()));
    StringBuilder data = new StringBuilder(150);
    String line;
    while ((line = rd.readLine()) != null)    data.append(line);
    rd.close();
    response = data.toString();
   
    if(connection instanceof HttpsURLConnection) sslConnection.disconnect();
    else if(connection instanceof HttpURLConnection) nonsslConnection.disconnect();
    
    return response;
}

Listing V
    
To create the HTTPS connection with the right SSL parameters, you use the javax.net.ssl.SSLSocketFactory. As shown in listing VI

SSLSocketFactory createSocketFactory() throws Exception {

      KeyStore keyStore;

       // This is a one-way authentication
       keyStore = KeyStore.getInstance("PKCS12");
       keyStore.load(new FileInputStream(new File("pfx file location")),
                 new String("pfx password").toCharArray());
        TrustManagerFactory trustFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
        trustFactory.init(keyStore);
        TrustManager[] tm = trustFactory.getTrustManagers();

        SSLContext context = SSLContext.getInstance("SSLv3");
        context.init(null, tm, null);
        SSLSocketFactory socketFactory = context.getSocketFactory();
        return socketFactory;
}

Listing VI


你可能感兴趣的:(SSL(TLS) Authentication:Web Services and Java)