Java动态代理模式
0x00 前言
基础知识决定上层建筑,我计划是先把JavaWeb RCE漏洞相关的基础概念都总结一遍后,再开始复现学习一些RCE的漏洞文章。
0x01 代理模式
在学习Java动态代理模式之前,先了解一下什么是代理模式。
代理模式是一种结构型设计模式, 让你能够提供对象的替代品或其占位符。 代理控制着对于原对象的访问, 并允许在将请求提交给对象前后进行一些处理。
它的好处就是如果需要在类的主要业务逻辑前后执行一些工作, 你无需修改类就能完成这项工作。 由于代理实现的接口与原类相同, 因此你可将其传递给任何一个使用实际服务对象的客户端。
代理模式角色分为 3 种:
Subject(抽象主题角色):定义代理类和真实主题的公共对外方法,也是代理类代理真实主题的方法;
RealSubject(真实主题角色):真正实现业务逻辑的类;
Proxy(代理主题角色):用来代理和封装真实主题;
代理模式的结构比较简单,其核心是代理类,为了让客户端能够一致性地对待真实对象和代理对象,在代理模式中引入了抽象层。
0x02 静态代理
有动态代理肯定就有静态代理,这里就先演示一下静态代理。
服务规范接口:
1 |
|
服务器本身:
1 |
|
代理服务器:
1 |
|
客户机进行使用服务:
1 |
|
输出结果:
1 |
|
实现proxy类对服务器本身类的封装对于粒度的控制有着重要的意义。但是静态代理这个模式本身有个大问题,如果类方法数量越来越多的时候,代理类的代码量是十分庞大的。所以需要引入动态代理来解决此类问题。
0x03 动态代理
创建动态代理类会使用到 jav.lang.reflect.Proxy类和jav.lang.reflect.InvocationHandler 接口。
jav.lang.reflect.Proxy 主要用于生成动态代理类 Clas、创建代理类实例,该类实现了 jav.io.Serializable接口。
接着上面的静态代理案例,我们演示下动态代理dome:
服务规范接口:
1 |
|
服务器本身:
1 |
|
代理服务器:
1 |
|
客户机进行使用服务:
1 |
|
输出结果:
1 |
|
InvocationHandler 和 Proxy 的主要方法介绍如下:
java.lang.reflect.InvocationHandler:
Object invoke(Object proxy, Method method, Object[] args) 定义了代理对象调用方法时希望执行的动作,用于集中处理在动态代理类对象上的方法调用
java.lang.reflect.Proxy:
static InvocationHandler getInvocationHandler(Object proxy) 用于获取指定代理对象所关联的调用处理器
static Class<?> getProxyClass(ClassLoader loader, Class<?>… interfaces) 返回指定接口的代理类
static Object newProxyInstance(ClassLoader loader, Class<?>[] interfaces, InvocationHandler h) 构造实现指定接口的代理类的一个新实例,所有方法会调用给定处理器对象的 invoke 方法
static boolean isProxyClass(Class<?> cl) 返回 cl 是否为一个代理类
Proxy.newProxyInstance() 方法创建动态代理。
newProxyInstance()方法有三个参数:
1、类加载器(ClassLoader)用来加载动态代理类。
2、一个要实现的接口的数组。
3、一个 InvocationHandler 把所有方法的调用都转到代理上。
0x04 动态代理调用过程
JDK动态代理执行方法调用的过程简图如下:
0x05 一些特性特点
JDK 动态代理只需要实现 InvocationHandler 接口,重写 invoke 方法便可以完成代理的实现;
jdk的代理是利用反射生成代理类 Proxyxx.class 代理类字节码,并生成对象;
jdk动态代理之所以只能代理接口是因为代理类本身已经extends了Proxy,而java是不允许多重继承的,但是允许实现多个接口;
JDK 动态代理是基于接口设计实现的,如果没有接口,会抛异常;
0x06 参考文章
[1] https://www.cnblogs.com/afanti/p/10199226.html
[2] https://www.zhihu.com/question/20794107
[3] https://wiki.jikexueyuan.com/project/java-reflection/java-dynamic.html
[4] http://laijianfeng.org/2018/12/Java-%E5%8A%A8%E6%80%81%E4%BB%A3%E7%90%86%E8%AF%A6%E8%A7%A3/