單例模式的反射漏洞和反序列化漏洞代碼實(shí)例
除了枚舉式單例模式外,其余4種在單例模式提到的單例模式的實(shí)現(xiàn)方式都存在反射漏洞和反序列化漏洞。
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
{
// 正常創(chuàng)建單例對(duì)象
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的構(gòu)造方法
cons.setAccessible(true); // 跳過方法的可見性檢查
SingletonLazy s3 = cons.newInstance(); // 調(diào)用構(gòu)造方法生成新對(duì)象
SingletonLazy s4 = cons.newInstance(); // 調(diào)用構(gòu)造方法生成新對(duì)象
System.out.println(s3);
System.out.println(s4);
// 用反序列化破解單例
FileOutputStream fos = new FileOutputStream("object.out"); // 文件輸出流
ObjectOutputStream oos = new ObjectOutputStream(fos); // 對(duì)象輸出流
oos.writeObject(s1); // 向文件序列化對(duì)象
oos.close(); // 關(guān)閉對(duì)象輸出流
fos.close(); // 關(guān)閉文件輸出流
FileInputStream fis = new FileInputStream("object.out"); // 文件輸入流
ObjectInputStream ois = new ObjectInputStream(fis); // 對(duì)象輸入流
SingletonLazy s5 = (SingletonLazy) ois.readObject(); // 從文件反序列化對(duì)象
ois.close(); // 關(guān)閉對(duì)象輸入流
fis.close(); // 關(guān)閉文件輸入流
System.out.println(s5);
}
}
運(yùn)行結(jié)果
singleton.SingletonLazy@15db9742 // s1
singleton.SingletonLazy@15db9742// s2
singleton.SingletonLazy@6d06d69c// s3
singleton.SingletonLazy@7852e922// s4
singleton.SingletonLazy@3b07d329 // s5
從運(yùn)行結(jié)果可以看到,通過反射可以得到私有構(gòu)造方法,從而實(shí)例化兩個(gè)不同的對(duì)象實(shí)例 codesingleton.SingletonLazy@6d06d69c}和{@code singleton.SingletonLazy@7852e922}. 通過反序列化,也可以得到新對(duì)象{@code singleton.SingletonLazy@3b07d329}.
以懶漢式單例模式的實(shí)現(xiàn)為例,解決反射漏洞和反序列化漏洞的方法如下:
package singleton;
import java.io.ObjectStreamException;
import java.io.Serializable;
/**
* 排除了反射漏洞和反序列化漏洞的懶漢式單例模式
* @author weiyx15
*
*/
public class SingletonLazySafe implements Serializable{
private static SingletonLazySafe instance;
private SingletonLazySafe() {
// 防止反射漏洞通過再次調(diào)用私有構(gòu)造方法實(shí)例化新的instance
if (instance != null)
{
throw new RuntimeException(); // 拋出運(yùn)行時(shí)異常
}
}
public static synchronized SingletonLazySafe getInstance() {
if (instance == null) // 如果未實(shí)例化,則先實(shí)例化
{
instance = new SingletonLazySafe(); // 調(diào)用getInstance方法后再實(shí)例化對(duì)象
}
return instance;
}
/**
* 從I/O流讀取對(duì)象時(shí)會(huì)調(diào)用readResolve接口
* 在readResolve接口中直接返回instance對(duì)象
* 避免反序列化時(shí)重新實(shí)例化對(duì)象
* @return 單例對(duì)象
* @throws ObjectStreamException
*/
private Object readResolve() throws ObjectStreamException {
return instance;
}
}
以上所述是小編給大家介紹的單例模式的反射漏洞和反序列化漏洞詳解整合,希望對(duì)大家有所幫助,如果大家有任何疑問請(qǐng)給我留言,小編會(huì)及時(shí)回復(fù)大家的。在此也非常感謝大家對(duì)腳本之家網(wǎng)站的支持!
相關(guān)文章
Java中NoClassDefFoundError?和?ClassNotFoundException的區(qū)別
Java中NoClassDefFoundError和ClassNotFoundException的區(qū)別,從類繼承層次上來看,ClassNotFoundException是從Exception繼承的,所以ClassNotFoundException是一個(gè)檢查異常。具體詳情需要的朋友可以參考下面文章內(nèi)容2022-06-06
spring NamedContextFactory實(shí)現(xiàn)服務(wù)隔離的示例詳解
假設(shè)我們有個(gè)場(chǎng)景,我們需要實(shí)現(xiàn)服務(wù)之間的數(shù)據(jù)隔離、配置隔離、依賴的spring bean之間隔離,大家會(huì)有什么實(shí)現(xiàn)思路?今天給大家介紹spring-cloud-context里面有個(gè)NamedContextFactory可以達(dá)到上面的效果,需要的朋友可以參考下2024-05-05
SpringCloud Finchley Gateway 緩存請(qǐng)求Body和Form表單的實(shí)現(xiàn)
在接入Spring-Cloud-Gateway時(shí),可能有需求進(jìn)行緩存Json-Body數(shù)據(jù)或者Form-Urlencoded數(shù)據(jù)的情況。這篇文章主要介紹了SpringCloud Finchley Gateway 緩存請(qǐng)求Body和Form表單的實(shí)現(xiàn),感興趣的小伙伴們可以參考一下2019-01-01
springboot如何添加task任務(wù)執(zhí)行隊(duì)列
這篇文章主要介紹了springboot如何添加task任務(wù)執(zhí)行隊(duì)列問題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-07-07

