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.

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");