介绍
本篇主要介绍java的RMI、JNDI、LDAP,在后面会详细分析log4j的jndi注入原理。
什么是RMI
RMI全称是Remote Method Invocatioon,也就是远程方法调用,看起来和RPC(Remote Procedure Call)很像
实际上它俩的确很像,RMI算是JAVA定制版RPC吧
一个完整的RMI调用过程,需要下面几个部分
- 注册服务
- RMIServer
- 客户端
- 接口
- 实现接口的类
执行流程如下
- 首先开启注册服务
- RMI创建实现接口的类的对象,并在注册服务中注册
- 客户端从注册服务调用接口里的方法
先来个例子,说不多说,都在代码里(网上找的)
注册服务代码
【→所有资源关注我,私信回复“资料”获取←】
1、网络安全学习路线
2、电子书籍(白帽子)
3、安全大厂内部视频
4、100份src文档
5、常见安全面试题
6、ctf大赛经典题目解析
7、全套工具包
8、应急响应笔记
接口和实现接口的类
[外链图片转存中…(img-0YGvrLnk-1646029690356)]
RMI服务
客户端
运行流程如下图
此图和上面的代码对应关系
Client -> Client
存根(stub) -> Client代码中的remoteHello对象(是个代理类,在通过它调用方法时,会将参数,函数名等信息打包,发送给骨架,存根对象包含了RMIServer的端口和ip)
rmiregistry -> RegServeer
Server -> RMI
骨架(Skeleton) -> 也是个代理类,监听4000端口,用于和存根通信,收到存根的请求后,去调用RemoteImp对应的方法,然后将结果返回给存根
ServiceImpl -> RemoteImpl
所以,再以上面的代码为例,解读下执行流程
先启动Register服务(默认端口1099)
RMI去连接Register服务,并将Name和存根发送给Register服务
如图
Client连接Register服务,根据Name获取到对应存根,再通过存根调用sayHello(“World”),因为存根是代理类,所以可以获取到函数名,参数,参数类型等信息,存根将这些信息打包,发给骨架
RMI的骨架也是代理类,通过反射调用remoteHello.sayHello(“World”),获取返回值Hello, World,并发送给存根
Client的存根将从骨架获取到的返回值Return,这样Client端看起来就好像调用的是本地的方法
补充下,以上步骤,通过网络传输的数据都是通过序列化对象的形式,使用的协议是JRMP(Java Remote Method Protocol)协议 很重要!!!
上面的代码还可以写成简化版
如图服务端,在启动注册中心的同时,设置了存根和名字
客户端,通过url连接注册中心,获取存根
什么是JNDI
JNDI全称是Java Naming and Directory Interfac