单例模式的反射漏洞和反序列化漏洞代码实例
除了枚举式单例模式外,其余4种在单例模式提到的单例模式的实现方式都存在反射漏洞和反序列化漏洞。
packagesingleton;
importjava.io.FileInputStream;
importjava.io.FileOutputStream;
importjava.io.ObjectInputStream;
importjava.io.ObjectOutputStream;
importjava.lang.reflect.Constructor;
/**
*用反射和反序列化的方法破解单例模式
*@authorweiyx15
*
*/
publicclassSingletonCrack{
publicstaticvoidmain(String[]args)throwsException
{
//正常创建单例对象
SingletonLazys1=SingletonLazy.getInstance();
SingletonLazys2=SingletonLazy.getInstance();
System.out.println(s1);
System.out.println(s2);
//用反射破解单例
Classcls=(Class)Class.forName("singleton.SingletonLazy"); //获取SingletonLazy类
Constructorcons=cls.getDeclaredConstructor(null); //获取SingletonLazy的构造方法
cons.setAccessible(true); //跳过方法的可见性检查
SingletonLazys3=cons.newInstance(); //调用构造方法生成新对象
SingletonLazys4=cons.newInstance(); //调用构造方法生成新对象
System.out.println(s3);
System.out.println(s4);
//用反序列化破解单例
FileOutputStreamfos=newFileOutputStream("object.out"); //文件输出流
ObjectOutputStreamoos=newObjectOutputStream(fos); //对象输出流
oos.writeObject(s1); //向文件序列化对象
oos.close(); //关闭对象输出流
fos.close(); //关闭文件输出流
FileInputStreamfis=newFileInputStream("object.out"); //文件输入流
ObjectInputStreamois=newObjectInputStream(fis); //对象输入流
SingletonLazys5=(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}和{@codesingleton.SingletonLazy@7852e922}.通过反序列化,也可以得到新对象{@codesingleton.SingletonLazy@3b07d329}.
以懒汉式单例模式的实现为例,解决反射漏洞和反序列化漏洞的方法如下:
packagesingleton;
importjava.io.ObjectStreamException;
importjava.io.Serializable;
/**
*排除了反射漏洞和反序列化漏洞的懒汉式单例模式
*@authorweiyx15
*
*/
publicclassSingletonLazySafeimplementsSerializable{
privatestaticSingletonLazySafeinstance;
privateSingletonLazySafe(){
//防止反射漏洞通过再次调用私有构造方法实例化新的instance
if(instance!=null)
{
thrownewRuntimeException(); //抛出运行时异常
}
}
publicstaticsynchronizedSingletonLazySafegetInstance(){
if(instance==null) //如果未实例化,则先实例化
{
instance=newSingletonLazySafe(); //调用getInstance方法后再实例化对象
}
returninstance;
}
/**
*从I/O流读取对象时会调用readResolve接口
*在readResolve接口中直接返回instance对象
*避免反序列化时重新实例化对象
*@return单例对象
*@throwsObjectStreamException
*/
privateObjectreadResolve()throwsObjectStreamException{
returninstance;
}
}
以上所述是小编给大家介绍的单例模式的反射漏洞和反序列化漏洞详解整合,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对毛票票网站的支持!