单例模式的反射漏洞和反序列化漏洞代码实例
除了枚举式单例模式外,其余4种在单例模式提到的单例模式的实现方式都存在反射漏洞和反序列化漏洞。
package singleton; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.ObjectInputStream; import java.io.ObjectOutputStream; import java.lang.reflect.Constructor; /** * 用反射和反序列化的方法破解单例模式 * @author weiyx15 * */ public class SingletonCrack { public static void main(String[] args) throws Exception { // 正常创建单例对象 SingletonLazy s1 = SingletonLazy.getInstance(); SingletonLazy s2 = SingletonLazy.getInstance(); System.out.println(s1); System.out.println(s2); // 用反射破解单例 Class<SingletonLazy> cls = (Class<SingletonLazy>) Class.forName("singleton.SingletonLazy"); // 获取SingletonLazy类 Constructor<SingletonLazy> cons = cls.getDeclaredConstructor(null); // 获取SingletonLazy的构造方法 cons.setAccessible(true); // 跳过方法的可见性检查 SingletonLazy s3 = cons.newInstance(); // 调用构造方法生成新对象 SingletonLazy s4 = cons.newInstance(); // 调用构造方法生成新对象 System.out.println(s3); System.out.println(s4); // 用反序列化破解单例 FileOutputStream fos = new FileOutputStream("object.out"); // 文件输出流 ObjectOutputStream oos = new ObjectOutputStream(fos); // 对象输出流 oos.writeObject(s1); // 向文件序列化对象 oos.close(); // 关闭对象输出流 fos.close(); // 关闭文件输出流 FileInputStream fis = new FileInputStream("object.out"); // 文件输入流 ObjectInputStream ois = new ObjectInputStream(fis); // 对象输入流 SingletonLazy s5 = (SingletonLazy) ois.readObject(); // 从文件反序列化对象 ois.close(); // 关闭对象输入流 fis.close(); // 关闭文件输入流 System.out.println(s5); } }
运行结果
singleton.SingletonLazy@15db9742 // s1
singleton.SingletonLazy@15db9742// s2
singleton.SingletonLazy@6d06d69c// s3
singleton.SingletonLazy@7852e922// s4
singleton.SingletonLazy@3b07d329 // s5
从运行结果可以看到,通过反射可以得到私有构造方法,从而实例化两个不同的对象实例 codesingleton.SingletonLazy@6d06d69c}和{@code singleton.SingletonLazy@7852e922}. 通过反序列化,也可以得到新对象{@code singleton.SingletonLazy@3b07d329}.
以懒汉式单例模式的实现为例,解决反射漏洞和反序列化漏洞的方法如下:
package singleton; import java.io.ObjectStreamException; import java.io.Serializable; /** * 排除了反射漏洞和反序列化漏洞的懒汉式单例模式 * @author weiyx15 * */ public class SingletonLazySafe implements Serializable{ private static SingletonLazySafe instance; private SingletonLazySafe() { // 防止反射漏洞通过再次调用私有构造方法实例化新的instance if (instance != null) { throw new RuntimeException(); // 抛出运行时异常 } } public static synchronized SingletonLazySafe getInstance() { if (instance == null) // 如果未实例化,则先实例化 { instance = new SingletonLazySafe(); // 调用getInstance方法后再实例化对象 } return instance; } /** * 从I/O流读取对象时会调用readResolve接口 * 在readResolve接口中直接返回instance对象 * 避免反序列化时重新实例化对象 * @return 单例对象 * @throws ObjectStreamException */ private Object readResolve() throws ObjectStreamException { return instance; } }
以上所述是小编给大家介绍的单例模式的反射漏洞和反序列化漏洞详解整合,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对脚本之家网站的支持!
相关文章
idea将maven项目改成Spring boot项目的方法步骤
这篇文章主要介绍了idea将maven项目改成Spring boot项目的方法步骤,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧2020-09-09Java中有界队列的饱和策略(reject policy)原理解析
这篇文章主要介绍了Java中有界队列的饱和策略(reject policy)原理解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下2020-04-04关于springboot中对sqlSessionFactoryBean的自定义
这篇文章主要介绍了springboot中对sqlSessionFactoryBean的自定义方式,具有很好的参考价值,希望对大家有所帮助。如有错误或未考虑完全的地方,望不吝赐教2021-12-12CMD运行Intellij Idea编译后的class文件操作
这篇文章主要介绍了CMD运行Intellij Idea编译后的class文件操作,具有很好的参考价值,希望对大家有所帮助。一起跟随小编过来看看吧2021-02-02
最新评论