java代码学习(九) ——RMI

RMI简介

Java RMI,即 远程方法调用(Remote Method Invocation),一种用于实现远程过程调用(RPC)(Remote procedure call)的Java API, 能直接传输序列化后的Java对象和分布式垃圾收集。它的实现依赖于Java虚拟机(JVM),因此它仅支持从一个JVM到另一个JVM的调用。

 java代码学习(九) ——RMI

 

 

Rmi的调用

服务端

import java.rmi.Naming;

import java.rmi.Remote;

import java.rmi.RemoteException;

import java.rmi.registry.LocateRegistry;

import java.rmi.server.UnicastRemoteObject;

 

public class RmiRegistry {

    public interface IRemoteHello extends Remote{

        public String hello() throws RemoteException;

    }

    public class RemoteHelloWorld extends UnicastRemoteObject implements

            IRemoteHello {

        protected RemoteHelloWorld() throws RemoteException {

            super();

        }

        public String hello() throws RemoteException {

            System.out.println("call from");

            return "Hello world";

        }

    }

    private void start() throws Exception {

        RemoteHelloWorld h = new RemoteHelloWorld();

        LocateRegistry.createRegistry(1099);

        Naming.rebind("rmi://127.0.0.1:1099/Hello", h);

    }

 

    public static void main(String[] args) throws Exception{

        new RmiRegistry().start();

    }

}

客户端

import java.rmi.Naming;

 

public class TrainMain {

    public static void main(String[] args) throws Exception {

        RmiRegistry.IRemoteHello hello = (RmiRegistry.IRemoteHello)

                Naming.lookup("rmi://127.0.0.1:1099/Hello");

        String ret = hello.hello();

        System.out.println( ret);

    }

}

 java代码学习(九) ——RMI 

成功从服务端取回hello world。

整个实现流程如下,客户端连接Registry,并在其中寻找Name是Hello的对象,这个对应数据 流中的Call消息;然后Registry返回⼀个序列化的数据,这个就是找到的Name=Hello的对象,这个对应 数据流中的ReturnData消息;客户端反序列化该对象,发现该对象是⼀个远程对象,地址在10.91.214.135:7532 ,于是再与这个地址建⽴TCP连接;在这个新的连接中,才执⾏真正远程⽅法调⽤,也就是 hello() 。

 

RMI的参与者

RMI Registry

RMI Server

RMI Client

攻击RMI Registry

RMI Registry是一个远程对象管理的地方,可以理解为一个远程对象的“后台”。我们可以尝试直

接访问“后台”功能。

注:远程访问RMI Registry时,只能通过list和lookup方法访问。rebind、bind、unbind方法只有来源地址是localhost时才能调用

只要目标服务器上存在一些危险方法,我们通过RMI就可以对其进行调用。

RMI动态类加载

当本地CLASSPATH中无法找到相应的类时,会在指定的codebase里加载class。codebase可以在系统属性java.rmi.server.codebase设置其URL。如果codebase的URL可控,那么我们就可以载入任意的class或jar文件。

RMI利用codebase执行任意代码

需要满足条件:

1.安装并配置了SecurityManager

2.Java版本低于7u21、6u45,或者设置了 java.rmi.server.useCodebaseOnly=false

注:在 java.rmi.server.useCodebaseOnly 配置为 true 的情况下,Java虚拟机将只信任预先配置好的

codebase ,不再支持从RMI请求中获取。

 




链接:https://www.jianshu.com/p/de85fad05dcb

https://www.anquanke.com/post/id/199481

 

上一篇:RabbitMQ学习-死信队列


下一篇:RMI实现细节详解