java安全-RMI

Java安全 - RMI

1、RMI原理浅析

RMI(Remote Method Invocation) 远程方法调用,是允许运行在一个JVM中的对象调用另一个JVM中的对象方法。两台虚拟机可以是同一台宿主机的不同进程,也可以运行在网络不同主机中,RMI基本结构是基于行为定义行为实现分离原则设计的,即用于定义行为的接口和行为的实现代码分离,且允许在不同JVM中运行。

行为定义行为实现RMI中体现在行为定义的代码写在服务端中继承了Remote的接口里,且允许不同的两个类实现同一个远程服务接口;而具体的行为实现一个类在服务端实现具体行为,另一个类在客户端作为远程服务代理提供客户端调用远程方法。

RMI分为三个部分:ServerClientRegistry

其中介绍一下Registry的作用,Registry是一个注册表,其中存放了远程对象的(ip、端口、标识符),它可以与服务端放在一起,也可以独立放在另一台JVM中。Client在调用远程方法时,并不直接与Server通信远程调用方法不直接与服务端通信,会通过名称服务NamingRegistry中查找注册的远程对象,由Registry提供远程对象的引用,其中提供了主机名,端口以及标识符,客户端再通过这些引用信息与远程服务端通过socket连接。

为什么使用Registry,其中一个很重要的原因是方便提供多服务端的远程服务,一个Registry中可以提供不同服务器的远程对象引用。

图中提及bindrebind两个方法,其实他们是不同的类方法,Registry.bindNaming.rebind

  • bind使用注册表进行绑定,由于该方法直接使用了保留有注册表信息的类,不需要实现完整的RMI URL
  • rebind,使用java中的Naming名称服务进行绑定,在RMI中,名称服务不仅仅提供注册表的路径查询,所以需要指明完整的RMI URL

例如

//通过注册表绑定远程对象引用
registry.rebind("Hello", remoteObj);
//通过Naming绑定远程对象
Naming.bind("rmi://127.0.0.1:1099/remote", remoteObj);

服务端实现

编写远程对象的接口,声明远程对象的方法,接口需要继承Remote

public interface RemoteObj extends Remote {
    public String Hello() throws RemoteException;
}

实现远程对象接口,需要继承UnicastRemoteObject

public class RemoteObjImpl extends UnicastRemoteObject implements RemoteObj {
    protected RemoteObjImpl() throws RemoteException {
        System.out.println("RemoteObjImpl的构造方法");
    }
    @Override
    public String Hello() {
        return "Hello World";
    }
}

服务端启动以及创建注册表

public class RMIServer {
    public static void main(String[] args) throws RemoteException, MalformedURLException, AlreadyBoundException {
        //创建远程对象
        RemoteObj remoteObj = new RemoteObjImpl();
        //创建注册表,设置端口1099
        Registry registry = LocateRegistry.createRegistry(1099);
        //通过注册表绑定远程对象引用
        registry.rebind("Hello", remoteObj);
        //通过Naming绑定远程对象
//        Naming.bind("rmi://127.0.0.1:1099/remote", remoteObj);
    }
}

客户端实现

获取需要调用的远程对象的接口,这里直接将接口写入客户端中模拟

public interface RemoteObj extends Remote {
    public String Hello();
}

客户端调用远程方法

public class RMIClient {
    public static void main(String[] args) throws MalformedURLException, NotBoundException, RemoteException {
        Registry registry = LocateRegistry.getRegistry("localhost",1099);
//        RemoteObj remoteObj = (RemoteObj) Naming.lookup("rmi://127.0.0.1:1099/Hello");
        RemoteObj remoteObj = (RemoteObj) registry.lookup("Hello");
        String ret = remoteObj.Hello();
        System.out.println(ret);
    }
}

server

client

接下来会继续更新(由于源码分析部分篇幅过长,单独写了一篇 https://www.cnblogs.com/p1a0m1a0/p/17071632.html)

posted @ 2023-01-28 01:26  PIAOMIAO1  阅读(158)  评论(0编辑  收藏  举报