[转载]基于ssl加密通信的rmi应用实现

来源:互联网 发布:javascript 文字滚动 编辑:程序博客网 时间:2024/06/06 00:48
原文地址:基于ssl加密通信的rmi应用实现作者:chunyv
  • 生产策略文件:java.policy内容如下:
    grant{  
          permission   java.security.AllPermission;
      };
  • 接口定义

    import java.rmi.Remote;
    import java.rmi.RemoteException;

    public interface MyRMI extends Remote {
     String execute() throws RemoteException;;
    }

  • 自定义本地SocketFactory

    import java.io.FileInputStream;
    import java.io.Serializable;
    import java.net.Socket;
    import java.rmi.server.RMIClientSocketFactory;
    import java.security.KeyStore;

    import javax.net.ssl.KeyManagerFactory;
    import javax.net.ssl.SSLContext;
    import javax.net.ssl.SSLSocket;
    import javax.net.ssl.TrustManagerFactory;

    public class RMISSLClientSocketFactory implements RMIClientSocketFactory,
      Serializable {
     
     String server_crt = null;
     String client_crt = null;
     String password = null;
     
     public RMISSLClientSocketFactory(String server_crt, String client_crt,
       String password)
     {
      this.server_crt = server_crt;
      this.client_crt = client_crt;
      this.password = password;
     }
     
     public Socket createSocket(String host, int port) {
      try {
       SSLContext ctx = SSLContext.getInstance("SSL");

       KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509");
       TrustManagerFactory tmf = TrustManagerFactory
         .getInstance("SunX509");

       KeyStore ks = KeyStore.getInstance("JKS");
       KeyStore tks = KeyStore.getInstance("JKS");

       ks.load(new FileInputStream(this.client_crt), this.password
         .toCharArray());
       tks.load(new FileInputStream(this.server_crt), this.password
         .toCharArray());

       kmf.init(ks, "123456".toCharArray());
       tmf.init(tks);

       ctx.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null);
       SSLSocket socket = (SSLSocket) ctx.getSocketFactory().createSocket(
         host, port);

       return socket;
      } catch (Exception err) {
       err.printStackTrace();
      }
      return null;
     }

     public int hashCode() {
      return getClass().hashCode();
     }

     public boolean equals(Object obj) {
      if (obj == this) {
       return true;
      } else if (obj == null || getClass() != obj.getClass()) {
       return false;
      }
      return true;
     }
    }

  • 自定义远程SocketFactory

    import java.io.FileInputStream;
    import java.io.IOException;
    import java.net.ServerSocket;
    import java.rmi.server.RMIServerSocketFactory;
    import java.security.KeyStore;

    import javax.net.ssl.KeyManagerFactory;
    import javax.net.ssl.SSLContext;
    import javax.net.ssl.SSLServerSocket;
    import javax.net.ssl.SSLServerSocketFactory;
    import javax.net.ssl.TrustManagerFactory;

    public class RMISSLServerSocketFactory implements RMIServerSocketFactory {

     private SSLServerSocketFactory ssf = null;

     public RMISSLServerSocketFactory(String server_crt, String client_crt,
       String password) throws Exception {
      try {
       SSLContext ctx = SSLContext.getInstance("SSL");

       KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509");
       TrustManagerFactory tmf = TrustManagerFactory
         .getInstance("SunX509");

       KeyStore ks = KeyStore.getInstance("JKS");
       KeyStore tks = KeyStore.getInstance("JKS");

       ks.load(new FileInputStream(server_crt), password.toCharArray());
       tks.load(new FileInputStream(client_crt), password.toCharArray());

       kmf.init(ks, password.toCharArray());
       tmf.init(tks);

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

       ssf = ctx.getServerSocketFactory();
       
      } catch (Exception err) {
       err.printStackTrace();
      }
     }

     public ServerSocket createServerSocket(int port) throws IOException {
      SSLServerSocket mysslsocket = (SSLServerSocket)ssf.createServerSocket(port);
      
      mysslsocket.setNeedClientAuth(true);
      
      return mysslsocket;
     }

     public int hashCode() {
      return getClass().hashCode();
     }

     public boolean equals(Object obj) {
      if (obj == this) {
       return true;
      } else if (obj == null || getClass() != obj.getClass()) {
       return false;
      }
      return true;
     }
    }

  • 远程服务


    import java.rmi.RMISecurityManager;
    import java.rmi.registry.LocateRegistry;
    import java.rmi.registry.Registry;
    import java.rmi.server.RemoteServer;
    import java.rmi.server.UnicastRemoteObject;

    public class RMIServer extends UnicastRemoteObject implements MyRMI {

     private static final int PORT = 8080;

     public RMIServer() throws Exception {
      super(PORT, new RMISSLClientSocketFactory("server.keystore",
        "client.keystore", "123456"),
        new RMISSLServerSocketFactory("server.keystore",
          "client.keystore", "123456"));
     }

     public static void main(String args[]) {

      if (System.getSecurityManager() == null) {
       System.setSecurityManager(new RMISecurityManager());
      }

      try {

       Registry registry = LocateRegistry.createRegistry(PORT,
         new RMISSLClientSocketFactory("server.keystore",
           "client.keystore", "123456"),
         new RMISSLServerSocketFactory("server.keystore",
           "client.keystore", "123456"));

       RMIServer obj = new RMIServer();

       registry.bind("HelloWorld", obj);

       System.out.println("HelloWorld bound in registry");
      } catch (Exception err) {
       err.printStackTrace();
      }
     }

     public String execute() {

      String clientaddr = null;

      try {

       clientaddr = RemoteServer.getClientHost();

       System.out.println("connect from " + clientaddr);

       return "hello client " + clientaddr;

      } catch (Exception err) {
       err.printStackTrace();
      }
      return "hello client ";
     }
    }

  • 本地服务


    import java.rmi.registry.LocateRegistry;
    import java.rmi.registry.Registry;

    public class RMIClient {

     private static final int PORT = 8080;

     public static void main(String args[]) {
      try {

       Registry registry = LocateRegistry.getRegistry("10.1.1.52", PORT,
         new RMISSLClientSocketFactory("server.keystore",
           "client.keystore", "123456"));

       MyRMI myrmi = (MyRMI) registry.lookup("HelloWorld");

       System.out.println(myrmi.execute());

      } catch (Exception e) {
       e.printStackTrace();
      }
     }
    }

  • 运行结果

    远程:

    HelloWorld bound in registry
    connect from 10.1.1.235

    本地:

    hello client 10.1.1.235

  • 1、操作方式
    一、生产key
    Server需要:
    1)KeyStore: 其中保存服务端的私钥
    2)Trust KeyStore:其中保存客户端的授权证书
    同样,Client需要:
    1)KeyStore:其中保存客户端的私钥
    2)Trust KeyStore:其中保存服务端的授权证书
     
    在这里我还是推荐使用Java自带的keytool命令,去生成这样信息文件。当然目前非常流行的开源的生成SSL证书的还有OpenSSL。OpenSSL用C语言编写,跨系统。但是我们可能在以后的过程中用java程序生成证书的方便性考虑,还是用JDK自带的keytool。


    1)生成服务端私钥,并且导入到服务端KeyStore文件中
    keytool -genkey -alias serverkey -keystore kserver.keystore
    过程中,分别需要填写,根据需求自己设置就行
    keystore密码:123456 
    名字和姓氏:jin
    组织单位名称:none
    组织名称:none
    城市或区域名称:BJ
    州或省份名称:BJ
    国家代码:CN
    serverkey私钥的密码,不填写和keystore的密码一致。这里千万注意,直接回车就行了,不用修改密码。否则在后面的程序中以及无法直接应用这个私钥,会报错。
     
     
    就可以生成kserver.keystore文件 
    server.keystore是给服务端用的,其中保存着自己的私钥


    2)根据私钥,导出服务端证书
    keytool -export -alias serverkey -keystore kserver.keystore -file server.crt
    server.crt就是服务端的证书


    3)将服务端证书,导入到客户端的Trust KeyStore中
    keytool -import -alias serverkey -file server.crt -keystore tclient.keystore
    tclient.keystore是给客户端用的,其中保存着受信任的证书


    采用同样的方法,生成客户端的私钥,客户端的证书,并且导入到服务端的Trust KeyStore中
    1)keytool -genkey -alias clientkey -keystore kclient.keystore
    2)keytool -export -alias clientkey -keystore kclient.keystore -file client.crt
    3)keytool -import -alias clientkey -file client.crt -keystore tserver.keystore


    如此一来,生成的文件分成两组
    服务端保存:kserver.keystore tserver.keystore
    客户端保存:kclient.keystore  tclient.kyestore


    2、书写java.policy文件


    3、在cmd中执行,如下:
    E:\workspace\studyDemo\bin\javaWebRmi>java -classpath E:/workspace/studyDemo/bin
     -Djava.security.manager -Djava.security.policy=E:/workspace/studyDemo/java.poli
    cy javaWebRmi.RMIServer
原创粉丝点击