JDK动态代理
用户接口:
1 2 3 4 5 6 7
| public interface IUser { void show();
void create();
void update(); }
|
用户实现类:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
|
public class UserImpl implements IUser{ public UserImpl(){
}
@Override public void show(){ System.out.println("执行 => 展示"); }
@Override public void create() { System.out.println("执行 => 创建"); }
@Override public void update() { System.out.println("执行 => 更新"); }
}
|
Proxy:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32
| import java.lang.reflect.Method;
public class UserProxy implements IUser{ IUser user; public UserProxy(){ } public UserProxy(IUser user){ this.user = user; }
@Override public void show(){ user.show(); System.out.println("Proxy:调用 => show"); }
@Override public void create() { user.create(); System.out.println("Proxy:调用 => create"); }
@Override public void update() { user.update(); System.out.println("Proxy:调用 => update"); } }
|
测试类:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
| import java.lang.reflect.Proxy;
public class ProxyTest { public static void main(String[] args){
IUser user = new UserImpl();
IUser userProxy = new UserProxy(user); userProxy.show(); userProxy.update(); userProxy.create(); } }
|
效果:
但是我们可以发现,上面的这种如果想对所有方法都进行代理,其实非常麻烦,每个函数方法都得写一遍
所以引出动态代理,可以自动找到对应的方法 不用重写了
ProxyTest:
1 2 3 4 5 6
|
InvocationHandler userinvocationHandler = new UserInvocationHandler(user); IUser userActiveProxy = (IUser) Proxy.newProxyInstance(user.getClass().getClassLoader(), user.getClass().getInterfaces(), userinvocationHandler);
userActiveProxy.create();
|
userinvocationHandler:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| import java.lang.reflect.InvocationHandler; import java.lang.reflect.Method;
public class UserInvocationHandler implements InvocationHandler {
IUser user;
public UserInvocationHandler(){
} public UserInvocationHandler(IUser user){ this.user = user; }
@Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable{ method.invoke(user, args); return null; } }
|
可以成功执行方法
但是没有 实现日志的效果 加一句话就ok了
解释作用:
找到一个漏洞利用的点 B.f
入口是A(O) -> O.f2 意思:A接收参数O 然后调用O的f2方法
此时,如果O是动态代理类 O接收参数 进行调用f方法
O(X) invoke -> X.f 此时只需要把X传为B即可调用B.f
作用总结:
- readObject -> 反序列化自动执行
- invoke -> 有函数调用
- 拼接两条链