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:
- Create a KeyStore and Generate a Public-Private Key
- Export a X.509 Certificate against above Key into a file
- Create a TrustStore and Import X.509 Certificate as a Trusted Certificate
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 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 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
No comments:
Post a Comment