【代码审计】JavaRMI

0x00 版权声明

JAVA基础系列是笔者学习@炼石星球的笔记,大部分文字描述取自星球内发布的教程文件,仅作学习。

0x01 概念简介

RMI(Remote Method Invocation,远程方法调用)是Java的一组拥护开发分布式应用程序的API。RMI使用Java语言接口定义了远程对象,它集合了Java序列化和Java远程方法协议(Java Remote Method Protocol)。 简单地说,原先的程序仅能在同一操作系统的方法调用,通过RMI可以变成在不同操作系统之间对程序中方法的调用。RMI依赖的通信协议是JRMP。JRMP: Java远程方法协议(Java Remote Method Protocol,JRMP ),是特定于Java技术的、用于查找和引用远程对象的协议。RMI对象是通过序列化方式进行传输的

RMI中涉及到三个角色,它们分别为服务端(Server),注册中心(Registry)和客户端(Client)

  • 服务端(Server):负责将远程对象绑定至注册中心。
  • 注册中心(Registry):服务端会将远程对象绑定至此。客户端会向注册中心查询绑定的远程对象。
  • 客户端(Client):与注册中心和服务端交互

RMI代码编写步骤:

  1. 创建远程接口及声明远程方法(SayHello.java)
  2. 实现远程接口及远程方法(继承UnicastRemoteObject)(SayHelloImpl.java)
  3. 启动RMI注册服务,并注册远程对象(RmiServer.java)
  4. 客户端查找远程对象,并调用远程方法(RmiClient.java)
  5. 执行程序:启动服务端RmiServer;运行客户端RmiClient进行调用

0x02 Demo

创建项目,在java目录新建method、rmiserver、rmiclient三个包。

01 创建远程接口及声明远程方法

远程方法中的接口均要继承 Remote ,实际上 Remote 类中没有任 何代码,继承也仅是为了说明该是接口使用于远程方法。

在 src.main.java.method 目录下新建一个名为 SayHello 的Java Interface,并键 入代码:

1
2
3
4
5
6
7
8
package method;

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

public interface sayHello extends Remote {
public String sayhello(String name) throws RemoteException;
}

02 实现远程接口及远程方法

此步骤编写远程方法中具体实现代码。需要注意的是,它必须继承UnicastRemoteObject 类,表明其可以作为远程对象,并可以被注册到注册中心, 最终可以让客户端远程调用。

在 src.main.java.method 目录下新建一个名为 SayHelloImpl 的Java Class,并键 入代码

1
2
3
4
5
6
7
8
9
10
11
12
package method;
import java.rmi.RemoteException;
import java.rmi.server.UnicastRemoteObject;
public class SayHelloImpl extends UnicastRemoteObject implements sayHello{
public SayHelloImpl() throws RemoteException {
super();
}
@Override
public String sayhello(String name) throws RemoteException {
return "Hello,i am " + name;
}
}

03 启动RMI注册服务,并注册远程对象

这个步骤我们是编写RMI服务端代码,需要将上面编写的远程方法注册到注册中心去。在 src.main.java.rmiserver 目录下新建一个名为 RmiServer 的Java Class,并键 入以下代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
package rmiserver;
import method.sayHello;
import method.SayHelloImpl;
import java.rmi.RemoteException;
import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;
public class RmiServer {
public static void main(String[] args) throws RemoteException {
System.out.println("远程方法创建等待调用ing......");
//创建远程对象
sayHello sayhello = new SayHelloImpl();
//创建注册表
Registry registry = LocateRegistry.createRegistry(1099);
//将远程对象注册到注册表里面,并且取名为sayhello
registry.rebind("sayhello",sayhello);
}
}

04 客户端查找远程对象,并调用远程方法

这个步骤我们是编写RMI客户端代码,主要是获取到注册中心代理,查询具体注册的远程方法并调用。在 src.main.java.rmiclient 目录下新建一个名为 RmiClient 的Java Class,并键入以下代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
package rmiclient;
import method.sayHello;
import java.rmi.NotBoundException;
import java.rmi.RemoteException;
import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;
public class RmiClient {
public static void main(String[] args) throws RemoteException, NotBoundException {
//获取到注册中心的代理
Registry registry = LocateRegistry.getRegistry("localhost",1099);
//利用注册中心的代理去查询远程注册表中名为sayhello的对象
sayHello sayhello = (sayHello) registry.lookup("sayhello");
//调用远程方法
System.out.println(sayhello.sayhello("admins zebra"));
}
}

05 执行程序:启动服务端RmiServer

首先运行RmiServer.main(),再运行RmiClient.main():

https://zebpic-1301715962.cos.ap-nanjing.myqcloud.com/blog/202210171606764.png