JavaSec 基础篇笔记
[toc]
Java 反射机制
java安全可以从反序列化说起,而反序列化漏洞又可以从反射说起,
Java 的反射机制是指在运行状态中,对于任意一个类都能够知道这个类所有的属性和方法;并且对于任意一个对象,都能够调用它的任意一个方法;这种动态获取信息以及动态调用对象方法的功能成为Java语言的反射机制。
反射是大多数语言里都必不可少的组成部分,对象可以通过反射获取他的类,类可以通过反射拿到所有方法(包括私有),拿到的方法可以调用,总之通过”反射”,我们可以将Java这种静态语言附加上动态特性。
Reference
Java 序列化和反序列化
Java 动态代理
代理模式
定义:为其他对象提供一种代理以控制对这个对象的访问
代理模式的通用类图
上图中,Subject是一个抽象类或者接口,RealSubject是实现方法类,具体的业务执行,Proxy则是RealSubject的代理,直接和client接触的。
代理模式可以在不修改被代理对象的基础上,通过扩展代理类,进行一些功能的附加与增强。值得注意的是,代理类和被代理类应该共同实现一个接口,或者是共同继承某个类。
代理模式优点
- 职责清晰
- 高扩展,只要实现了接口,都可以用代理。
- 智能化,动态代理。
分类
代码:GitHub
1、静态代理
以租房为例,我们一般用租房软件、找中介或者找房东。这里的中介就是代理者。
首先定义一个提供了租房方法的接口。
1 | public interface IRentHouse { |
定义租房的实现类
1 | public class RentHouse implements IRentHouse { |
我要租房,房源都在中介手中,所以找中介
1 | public class IntermediaryProxy implements IRentHouse { |
这里中介也实现了租房的接口。
再main方法中测试
1 | public class Main { |
返回信息
1 | 交中介费 |
这就是静态代理,因为中介这个代理类已经事先写好了,只负责代理租房业务
2、强制代理
如果我们直接找房东要租房,房东会说我把房子委托给中介了,你找中介去租吧。这样我们就又要交一部分中介费了,真坑。
来看代码如何实现,定义一个租房接口,增加一个方法。
1 | public interface IRentHouse { |
这时中介的方法也稍微做一下修改
1 | public class IntermediaryProxy implements IRentHouse { |
其中的getProxy()方法返回中介的代理类对象
我们再来看房东是如何实现租房:
1 | public class LandLord implements IRentHouse { |
房东的getProxy方法返回的是代理类,然后判断租房方法的调用者是否是中介,不是中介就不租房。
main方法测试:
1 | public static void main(String[] args){ |
看,这样就是强制你使用代理,如果不是代理就没法访问。
3、动态代理
我们知道现在的中介不仅仅是有租房业务,同时还有卖房、家政、维修等得业务,只是我们就不能对每一个业务都增加一个代理,就要提供通用的代理方法,这就要通过动态代理来实现了。
中介的代理方法做了一下修改
1 | public class IntermediaryProxy implements InvocationHandler { |
在这里实现InvocationHandler接口,此接口是JDK提供的动态代理接口,对被代理的方法提供代理。其中invoke方法是接口InvocationHandler定义必须实现的, 它完成对真实方法的调用。动态代理是根据被代理的接口生成所有的方法,也就是说给定一个接口,动态代理就会实现接口下所有的方法。通过 InvocationHandler接口, 所有方法都由该Handler来进行处理, 即所有被代理的方法都由 InvocationHandler接管实际的处理任务。
这里增加一个卖房的业务,代码和租房代码类似。
main方法测试:
1 | public static void main(String[] args){ |
在main方法中我们用到了Proxy这个类的方法,
1 | public static Object newProxyInstance(ClassLoader loader, |
loder:类加载器,interfaces:代码要用来代理的接口, h:一个 InvocationHandler 对象 。
InvocationHandler 是一个接口,每个代理的实例都有一个与之关联的 InvocationHandler 实现类,如果代理的方法被调用,那么代理便会通知和转发给内部的 InvocationHandler 实现类,由它决定处理。
1 | public interface InvocationHandler { |
InvocationHandler 内部只是一个 invoke() 方法,正是这个方法决定了怎么样处理代理传递过来的方法调用。
因为,Proxy 动态产生的代理会调用 InvocationHandler 实现类,所以 InvocationHandler 是实际执行者。
总结
- 静态代理,代理类需要自己编写代码写成。
- 动态代理,代理类通过 Proxy.newInstance() 方法生成。
- JDK实现的代理中不管是静态代理还是动态代理,代理与被代理者都要实现两样接口,它们的实质是面向接口编程。CGLib可以不需要接口。
- 动态代理通过 Proxy 动态生成 proxy class,但是它也指定了一个 InvocationHandler 的实现类。
Reference
设计模式(四)——搞懂什么是代理模式 - 知乎 (zhihu.com)
Java 类加载机制
Reference
java - Java类加载机制和对象创建过程_个人文章 - SegmentFault 思否
Java 字节码
参考
https://www.bilibili.com/video/BV16h411z7o9/?spm_id_from=333.999.0.0