Java安全初探-RMI篇
Posted deadf1sh-cat
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Java安全初探-RMI篇相关的知识,希望对你有一定的参考价值。
Java RMI初识
Java RMI 定义
Java RMI(Java Remote Method Invocation),即Java远程方法调用。是Java编程语言里,一种用于实现远程过程调用的应用程序编程接口。 Java RMI 使用 JRMP(Java Remote Message Protocol,Java远程消息交换协议)实现,使得客户端运行的程序可以调用远程服务器上的对象。是实现RPC的一种方式。
JRMP:Java Remote Message Protocol ,Java 远程消息交换协议。这是运行在Java RMI之下、TCP/IP之上的线路层协议。
注:Java RMI默认使用JRMP协议,而Weblogic RMI使用的是T3协议,此处应进行区分
RMI的交互
此处引用文章JAVA RMI 原理和使用浅析的一张图演示RMI的交互过程
对于RMI流程的解释,网上有很多不错的回答,此处不过多阐述。通俗来讲,便是RMI Registry作为client和server的中间人,假设服务端是商品仓库,客户端是购买者,则RMI Registry就是中介,只负责告诉客户可以售卖的商品相关信息。仓库在中介处登记可售商品,客户从中介处查看可购买的商品。客户从中介处获得商品的相关信息,然后交给跑腿(存根stub)去跟仓库人员(骨架skeleton)取货,双方商品信息确认一致,进行交易,客户获得商品。(可能比喻有点不恰当,别揍我qwq...
RMI 尝试
此处为了更能体会rmi原理,不把server和client放在同一个机器,而是将服务器放在虚拟机中,测试环境均为1.8u211
编写远程服务接口,该接口必须继承 java.rmi.Remote 接口,方法必须抛出java.rmi.RemoteException 异常;
编写远程接口实现类,该实现类必须继承 java.rmi.server.UnicastRemoteObject 类;
运行 RMI 编译器(rmic),创建客户端 stub 类和服务端 skeleton 类;
启动一个 RMI 注册表,以便驻留这些服务;
在 RMI 注册表中注册服务;
客户端查找远程对象,并调用远程方法;
注意:这里踩了个小坑,RMI 抛出异常 no security manager: RMI class loader disabled,新手容易遇到这个问题。这是因为在编译class文件的时候,这个class文件内部已经包含了package test.org;这样的内容,如果在部署的时候,不严格按照这个目录部署的话,服务器就会找不到。所以服务器和客户端在路径上要保持一致。
Server测试例
org
└─test
├─RMI
│ RMIServer.java
│
└─Server
Hello.java
//RMIServer.java
package org.test.RMI;
import java.rmi.Naming;
import java.rmi.RemoteException;
import java.rmi.registry.LocateRegistry;
import java.rmi.server.UnicastRemoteObject;
import org.test.Server.Hello;
public class RMIServer {
public class RemoteHelloWorld extends UnicastRemoteObject implements Hello {
protected RemoteHelloWorld() throws RemoteException {
super();
}
public String hello() throws RemoteException {
System.out.println("call from");
return "Hello DEADF1SH_CAT~";
}
}
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 RMIServer().start();
}
}
//Hello.java
package org.test.Server;
import java.rmi.Remote;
import java.rmi.RemoteException;
public interface Hello extends Remote {
public String hello() throws RemoteException;
}
Client测试例
org
└─test
├─client
│ TrainMain.java
│
└─Server
Hello.java
//TrainMain.java
package org.test.client;
import java.rmi.Naming;
import org.test.Server.Hello;
public class TrainMain {
public static void main(String[] args) throws Exception {
Hello hello = (Hello) Naming.lookup("rmi://192.168.247.128:1099/Hello");
String ret = hello.hello();
System.out.println(ret);
}
}
//Hello.java
package org.test.Server;
import java.rmi.Remote;
import java.rmi.RemoteException;
public interface Hello extends Remote {
public String hello() throws RemoteException;
}
服务器输出
客户端输出
可以看出客户端成功调用了服务器的RemoteHelloWorld对象的hello方法
RMI数据包分析
对上述调用过程进行抓包分析
- 1-5为tcp三次握手和网关转发报文
- 6-12为RMI通信数据(其中TCP报文为确认报文)
来看看9号RMI Call报文(远程对象请求)
用SerializationDumper这个工具对Java序列化数据进行分析
F:Java>java -jar SerializationDumper.jar aced00057722000000000000000000000000000000000000000000000000000244154dc9d4e63bdf74000548656c6c6f
STREAM_MAGIC - 0xac ed
STREAM_VERSION - 0x00 05
Contents
TC_BLOCKDATA - 0x77
Length - 34 - 0x22
Contents - 0x000000000000000000000000000000000000000000000000000244154dc9d4e63bdf
TC_STRING - 0x74
newHandle 0x00 7e 00 00
Length - 5 - 0x00 05
Value - Hello - 0x48656c6c6f
相关链接
以上是关于Java安全初探-RMI篇的主要内容,如果未能解决你的问题,请参考以下文章