Thursday, 4 July 2013

Java Remote Method Invocation (RMI) with Secure Socket Layer (SSL)

In this post I will demonstrate how a Java Remote Method Invocation (RMI) application can make remote invocations over Secure Socket Layer (SSL) connections.

Environment

Microsoft Windows 7
java version "1.7.0_09"
Java(TM) SE Runtime Environment (build 1.7.0_09-b05)
Java HotSpot(TM) 64-Bit Server VM (build 23.5-b02, mixed mode)
 

Before we actually start coding the RMI Client and Server, we have to do following:

Define RMI Remote Interface

/**
* Java Remote Method Invocation (RMI) with Secure Socket Layer (SSL)
* http://codeoftheday.blogspot.com/2013/07/java-remote-method-invocation-rmi-with.html
*/
package smhumayun.codeoftheday.RmiOverSslTest;
import java.rmi.Remote;
import java.rmi.RemoteException;
/**
* Central Time Service is used by all clients to synchronize time with server
*
* User: smhumayun
* Date: 7/4/13
* Time: 8:20 AM
*/
public interface CentralTimeService extends Remote {
/**
* Port where this service is exposed via RMI over SSL
*/
int PORT = 8844;
/**
* Return current time in milliseconds on server
*
* @return current time on server in milliseconds
* @throws RemoteException
*/
long getTime () throws RemoteException;
}

Implement RMI Remote Interface

/**
* Java Remote Method Invocation (RMI) with Secure Socket Layer (SSL)
* http://codeoftheday.blogspot.com/2013/07/java-remote-method-invocation-rmi-with.html
*/
package smhumayun.codeoftheday.RmiOverSslTest;
import javax.rmi.ssl.SslRMIClientSocketFactory;
import javax.rmi.ssl.SslRMIServerSocketFactory;
import java.rmi.RemoteException;
import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;
import java.rmi.server.UnicastRemoteObject;
/**
* Implementation of {@link CentralTimeService}
*
* User: smhumayun
* Date: 7/4/13
* Time: 8:25 AM
*/
public class CentralTimeServiceImpl extends UnicastRemoteObject implements CentralTimeService {
/**
* Creates and exports a new UnicastRemoteObject object using an
* anonymous port.
*
* @throws java.rmi.RemoteException if failed to export object
* @since JDK1.1
*/
protected CentralTimeServiceImpl() throws RemoteException {
super(0,
new SslRMIClientSocketFactory(),
new SslRMIServerSocketFactory(null, null, true));
}
/**
* Return current time in milliseconds on server
*
* @return current time on server in milliseconds
* @throws RemoteException
*/
@Override
public long getTime() throws RemoteException {
return System.currentTimeMillis();
}
/**
* Main method to start server
*
* @param args arguments
*/
public static void main(String args[]) {
try {
// Get SSL-based registry
Registry registry = LocateRegistry.getRegistry(null, CentralTimeService.PORT, new SslRMIClientSocketFactory());
//Create new impl object
CentralTimeServiceImpl centralTimeServiceImpl = new CentralTimeServiceImpl();
// Bind this object instance to the name "CentralTimeService"
registry.bind("CentralTimeService", centralTimeServiceImpl);
System.out.println("CentralTimeService bound in registry");
} catch (Exception e) {
System.out.println("CentralTimeServiceImpl Error : " + e.getMessage());
e.printStackTrace();
}
}
}

Create RMI Client which will consume/invoke RMI method remotely

/**
* Java Remote Method Invocation (RMI) with Secure Socket Layer (SSL)
* http://codeoftheday.blogspot.com/2013/07/java-remote-method-invocation-rmi-with.html
*/
package smhumayun.codeoftheday.RmiOverSslTest;
import javax.rmi.ssl.SslRMIClientSocketFactory;
import java.rmi.AccessException;
import java.rmi.NotBoundException;
import java.rmi.RemoteException;
import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;
import java.text.SimpleDateFormat;
import java.util.Date;
/**
* Client which consumes {@link CentralTimeService}
*
* User: smhumayun
* Date: 7/4/13
* Time: 8:34 AM
*/
public class CentralTimeServiceClient {
public static void main(String args[]) {
try {
//Make reference to SSL-based registry
Registry registry = LocateRegistry.getRegistry(null, CentralTimeService.PORT, new SslRMIClientSocketFactory());
//Create a reference to the remote object that implements the "CentralTimeService"
CentralTimeService centralTimeService = (CentralTimeService) registry.lookup("CentralTimeService");
//Invoke RMI call
long serverTime = centralTimeService.getTime();
System.out.println("Central Server Time is " + SimpleDateFormat.getDateTimeInstance().format(new Date(serverTime)));
} catch (AccessException e) {
e.printStackTrace();
} catch (RemoteException e) {
e.printStackTrace();
} catch (NotBoundException e) {
e.printStackTrace();
}
}
}

Finally, create RMI Registry

/**
* Java Remote Method Invocation (RMI) with Secure Socket Layer (SSL)
* http://codeoftheday.blogspot.com/2013/07/java-remote-method-invocation-rmi-with.html
*/
package smhumayun.codeoftheday.RmiOverSslTest;
import javax.rmi.ssl.SslRMIClientSocketFactory;
import javax.rmi.ssl.SslRMIServerSocketFactory;
import java.rmi.registry.LocateRegistry;
/**
* RMI Registry
*
* User: smhumayun
* Date: 7/4/13
* Time: 8:40 AM
*/
public class RmiRegistry {
public static void main(String[] args) throws Exception
{
// Start RMI registry on configured port
LocateRegistry.createRegistry(CentralTimeService.PORT, new SslRMIClientSocketFactory(), new SslRMIServerSocketFactory(null, null, true));
System.out.println("RMI registry running on port " + CentralTimeService.PORT);
// Sleep forever
Thread.sleep(Long.MAX_VALUE);
}
}

Copy ‘test-keystore’ created here and ‘test-truststore’ created here to the folder where your compiled classes reside.

Now, open up a console/command prompt and ‘cd’ to the directory where your compiled class files are, and:

Run RMIRegistry

java -Djavax.net.ssl.keyStore=test-keystore -Djavax.net.ssl.keyStorePassword=test-keystore-pwd -Djavax.net.ssl.trustStore=test-truststore -Djavax.net.ssl.trustStorePassword=test-truststore-pwd smhumayun.codeoftheday.RmiOverSslTest.RmiRegistry

Run RmiRegistry

Run CentralTimeServiceImpl

java -Djavax.net.ssl.keyStore=test-keystore -Djavax.net.ssl.keyStorePassword=test-keystore-pwd -Djavax.net.ssl.trustStore=test-truststore -Djavax.net.ssl.trustStorePassword=test-truststore-pwd smhumayun.codeoftheday.RmiOverSslTest.CentralTimeServiceImpl

Run CentralTimeServiceImpl

Run CentralTimeServiceClient

java -Djavax.net.ssl.keyStore=test-keystore -Djavax.net.ssl.keyStorePassword=test-keystore-pwd -Djavax.net.ssl.trustStore=test-truststore -Djavax.net.ssl.trustStorePassword=test-truststore-pwd smhumayun.codeoftheday.RmiOverSslTest.CentralTimeServiceClient

Run CentralTimeServiceClient

CLICK HERE TO DOWNLOAD COMPLETE SOURCE CODE

No comments:

Post a Comment