Java Webservice using HTTPS part 2

This article shows how to implement a HTTPS web service connection where the server only allows trusted clients to connect. It extends and uses the information given in this article “Java Webservice using HTTPS part 1”.

First, it is necessary to create a certificate for the client and to store it in the client’s keystone:

keytool -genkey -keystore client_keystore.ks -alias client  

This certificate must be exported from the client’s keystore…

keytool -export -alias client -keystore client_keystore.ks -file client.cer  

and imported into the server’s truststore:

keytool -import -alias client -file client.cer -keystore server_truststore.ks  

The server must now be given the information about the truststore, and must request the client authentication:

import javax.net.ssl.KeyManagerFactory;  
import javax.net.ssl.SSLContext;  
import javax.net.ssl.SSLParameters;  
import javax.net.ssl.TrustManagerFactory;  
import javax.xml.ws.Endpoint;  
import com.sun.net.httpserver.HttpContext;  
import com.sun.net.httpserver.HttpServer;  
import com.sun.net.httpserver.HttpsConfigurator;  
import com.sun.net.httpserver.HttpsParameters;  
import com.sun.net.httpserver.HttpsServer;  

httpsServer = HttpsServer.create(new InetSocketAddress(interfaceName, port), 0);  
SSLContext sslContext = SSLContext.getInstance("TLS");

// keystore  
char[] keystorePassword = "keystore_password".toCharArray();  
KeyStore ks = KeyStore.getInstance("JKS");  
ks.load(new FileInputStream("server_keystore.ks"), keystorePassword);  
KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509");  
kmf.init(ks, keystorePassword);  
// truststore  
TrustManagerFactory tmf = TrustManagerFactory.getInstance("SunX509");  
char[] truststorePassword = "truststore_password".toCharArray();  
ks.load(new FileInputStream("server_truststore.ks"), truststorePassword);  
tmf.init(ks);

sslContext.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null);

HttpsConfigurator configurator = new HttpsConfigurator(sslContext) {  
 /* (non-Javadoc)  
 * @see com.sun.net.httpserver.HttpsConfigurator#configure(com.sun.net.httpserver.HttpsParameters)  
 */  
 @Override  
 public void configure(HttpsParameters params) {  
 SSLParameters sslParams = getSSLContext().getDefaultSSLParameters();  
 sslParams.setNeedClientAuth(true);  
 params.setSSLParameters(sslParams);  
 }  
 };  
httpsServer.setHttpsConfigurator(configurator);

HttpContext httpContext = httpsServer.createContext("/path");  
Endpoint endpoint = Endpoint.create(serviceImpl);  
endpoint.publish(httpContext);  
  
httpsServer.start()  

For the client, in addition to the truststore settings, now it is necessary to set the System properties for the keystore (either as shown from within the client or by passing the corresponding -D arguments to the Java VM):

System.getProperties().put("javax.net.ssl.trustStore", "client_truststore.ks");  
System.getProperties().put("javax.net.ssl.trustStorePassword", "truststore_password");  
System.getProperties().put("javax.net.ssl.keyStore", "client_keystore.ks");  
System.getProperties().put("javax.net.ssl.keyStorePassword", "keystore_password");