Java代码审计学习笔记之JAVA基础系列(六、RMI)

1.RMI简介

RMI(Remote Method Invocation)即远程方法调用。 RMI的概念非常类似于windows操作系统中的RPC。它可以允许一个java虚拟机中的程序远程的调用另一个java虚拟机中的程序,具体执行的代码是在被调用程序所在的机器中执行的

2.编写一个RMI服务端

编写一个RMI服务端需要完成以下三个部分的内容。

  • 1.一个继承了java.rmi.Remote的接口
//IRemoteHello.java
import java.rmi.Remote;
import java.rmi.RemoteException;

public interface IRemoteHello extends Remote {
    public String hello() throws RemoteException;
}
  • 2.一个继承了java.rmi.server.UnicastRemoteObject并实现了上述接口的类
//RemoteHello.java
import java.rmi.RemoteException;
import java.rmi.server.UnicastRemoteObject;

public class RemoteHello extends UnicastRemoteObject implements IRemoteHello {

    protected RemoteHello() throws RemoteException{
    }

    public String hello()  throws RemoteException {
        System.out.println("GET A RMI CALL!");
        return "Hello";
    }
}
  • 3.一个创建Registry,实例化上述类并绑定的主类。
//RMIServer.java
import java.net.MalformedURLException;
import java.rmi.AlreadyBoundException;
import java.rmi.Naming;
import java.rmi.RemoteException;
import java.rmi.registry.LocateRegistry;

public class RMIServer {
    public static void main(String[] args) throws Exception {
        RemoteHello h = new RemoteHello();
        LocateRegistry.createRegistry(1099);
        Naming.bind("rmi://127.0.0.1:1099/hello",h);
    }
}

上述代码,当运行RMIServer.javamain方法时java程序将会监听1099端口,等待客户端连接。

3.编写一个RMI客户端

客户端只需要知道远程服务端实现的接口和绑定的rmi地址即可远程调用。因此客户端需要的文件如下:

  • 1.和服务端那边一样的接口文件
//IRemoteHello.java
import java.rmi.Remote;
import java.rmi.RemoteException;

public interface IRemoteHello extends Remote {
    public String hello() throws RemoteException;
}
  • 2.调用远程方法的主类
import java.net.MalformedURLException;
import java.rmi.Naming;
import java.rmi.NotBoundException;
import java.rmi.RemoteException;

public class RMIClient {
    public static void main(String[] args) throws RemoteException, MalformedURLException, NotBoundException {
        IRemoteHello hello = (IRemoteHello) Naming.lookup("rmi://192.168.1.103:1099/hello");
        String ret = hello.hello();
        System.out.println(ret);
    }
}

可以看到,客户端并不需要知道实现了IRemoteHello接口类的具体代码,唯一需要做的事情就是调用该接口里面的方法。上述代码运行后,即可远程调用该IRemoteHello接口中的hello方法,如下图:

客户端得到返回结果hello

服务端输出指定内容,说明具体代码确实是在服务端执行的