本文已参与「新人创作礼」活动,一起开启掘金创作之路。
首先咱们得对java有个了解,很多入门都不知道java是干嘛的,java是一个什么语言
java是一门面向对象的编程语言,在java中对象通常包括实例变量和方法两种属性
实例变量:他代表的是一种状态(数据),并且同一个类型的多个对象都独立地拥有这些状态,我们把对象看作类的一个实例
方法:我们在构造一个类的时候,除了初始化类的状态,还要构造出可以操作这种状态的方法。类不是对象,类是用来构造对象的。
JNDI
这个是java naming and directory interface的缩写(JAVA命名和目录接口)。这个东西的作用主要是为java应用程序提供命名和目录访问服务的API(应用程序编程入口)。 JNDI就是定义一个数据源,与系统外部资源的引用,都可以通过JNDI定义和引用
咱们学习JAVA反序列化的时候,经常遇到RMI,JNDI,LDAP这些概念 RMI: 基于序列化的java远程方法调用机制,作为一个常见的反序列化入口,它和反序列化漏洞的关系很大
RMI
java RMI 即远程方法调用(Remote Method Invocation) 是一种用于实现远程调用RPC(Remote procedure call)的java api,它能够直接传输序列化后的java对象和分布式垃圾收集。 他的实现依赖于JAVA虚拟机(JVM)。因此它仅支持从一个JVM到另一个JVM的调用
上面是RMI架构图
首先咱们从服务端入手,要提供一个rmi服务端不需要额外引入依赖,直接使用类似于我们常见的rpc框架,先提供一个接口,重点注意它需要继承接口对应的实现类。最后就是启动服务,提供一个上面的接口。
一个完整的RMI调用过程:
注册服务
RMIServer
客户端
接口
实现接口的类
流程就是首先开启注册服务,RMI创建实现接口的类的对象,客户端从注册服务调用接口里的方法
接口和实现接口的类
import java.rmi.Remote;
import java.rmi.RemoteException;
public interface RemoteIntF extends Remote {
String sayhello(String name) throws RemoteException;
}
对于RMI
import java.io.IOException;
import java.rmi.AlreadyBoundException;
import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;
import java.rmi.server.UnicastRemoteObject;
public class RMI {
public static void main(String[] args) {
RemoteImp remoteHello = new RemoteImp();
try {
RemoteIntF stub = (RemoteIntF) UnicastRemoteObject.exportObject(remoteHello, port 4000); //这里是导出服务,使用的4000端口
Registry registry = LocateRegistry.getRegistry(host: "127.0.0.1",port: 8000); //获取Registry
Registry.bind(name: "hello",stub); //使用名字hello,将服务注册到Regisstry
}catch (AlreadyBoundExceptioin | IOException e) {
e.printStackTrace();
}
}
}
Client -> Client存根(stub) -> Client代码中的remoteHello对象(是一个代理类,在通过它调用方法时,会将参数,函数名等信息打包,发送给骨架,存根对象包含了RMIServer的端口和IP) -> RegServeerServer -> RMI骨架(Skeleton) -> 也是个代理类,监听4000端口,用于和存根通信,收到存根的请求后,去调用RemoteImp对应的方法,然后将结果返回给ServiceImpl -> RemoteImpl