单例模式反射序列化漏洞及解决方案!
Posted Java技术栈
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了单例模式反射序列化漏洞及解决方案!相关的知识,希望对你有一定的参考价值。
Java技术栈
www.javastack.cn
![单例模式反射、序列化漏洞及解决方案!](https://image.cha138.com/20210418/edeb8ed8e2304298bfdb2dd459df2e92.jpg)
当我们需要获取Singleton对象的时候,直接调用静态方法getInstance就可以了:
![单例模式反射、序列化漏洞及解决方案!](https://image.cha138.com/20210418/cc4dedc1207448b595e37c5e6a7a05af.jpg)
但是学过反射的人都知道,通过反射技术也能获取到一个类的实例对象,即使它的构造函数时私有化的,我们也可以通过暴力访问来调用其构造函数,所以以上测试类的运行结果为:
![单例模式反射、序列化漏洞及解决方案!](https://image.cha138.com/20210418/cc4dedc1207448b595e37c5e6a7a05af.jpg)
可以看出通过调用getInstance方法获取到的实例是一样的,但是通过反射获取到的实例却是不同的,违反了模式的思想,那么我们应该怎么解决呢?我们只需要在私有的构造函数中加入一个判断即可:
![单例模式反射、序列化漏洞及解决方案!](https://image.cha138.com/20210418/3cad10dedda5495f93aa57e0df0ed1cf.jpg)
此时,我们再次启动测试类,获得到以下结果:
![单例模式反射、序列化漏洞及解决方案!](https://image.cha138.com/20210418/f1b92e53767c4727aaf56b6aece61540.jpg)
当然,就解决了使用反射技术来获取不同实例的问题了。
使用序列化及反序列化技术获取不同的实例:
如果我们的单例类实现了Serializable接口,那么这个类就能进行序列化和反序列化,测试代码如下:
![单例模式反射、序列化漏洞及解决方案!](https://image.cha138.com/20210418/5546d6cf60b844c080b794a25f5357d7.jpg)
运行结果如下:
![单例模式反射、序列化漏洞及解决方案!](https://image.cha138.com/20210418/b32dba1e1fc2484282dd9445abf6806a.jpg)
我们发现进过序列化及反序列化之后对象的引用就改变了,显然也是违反了单例设计模式的思想的,跟踪readObject源码后,发现这个方法会先写出一个newInstance,然后判断这个对象中是否存在readResolve这个方法,如果不存在,那么直接返回这个newInstance,如果存在,那么就调用readResolve这个方法,将这个方法的返回值返回给readObject.源码片段如下:
![单例模式反射、序列化漏洞及解决方案!](https://image.cha138.com/20210418/c42f23e3987f4613820561a435bd4f8d.jpg)
![单例模式反射、序列化漏洞及解决方案!](https://image.cha138.com/20210418/b12308e357a84cc4a3e10f56befb11f0.jpg)
由上可知,我们只需要在Singleton这个类中添加一个readResolve这个方法即可。
![单例模式反射、序列化漏洞及解决方案!](https://image.cha138.com/20210418/5081ee0ca1f14949a473066fd30bd836.jpg)
再次启用测试类,运行结果如下:
https://my.oschina.net/u/3441184/blog/884767
END
学习资料:
最近热文:
点击「阅读原文」带你飞~
以上是关于单例模式反射序列化漏洞及解决方案!的主要内容,如果未能解决你的问题,请参考以下文章