您好,登錄后才能下訂單哦!
這篇文章給大家分享的是有關單例模式中反射漏洞和反序列化漏洞的示例分析的內容。小編覺得挺實用的,因此分享給大家做個參考,一起跟隨小編過來看看吧。
除了枚舉式單例模式外,其余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; } }
感謝各位的閱讀!關于“單例模式中反射漏洞和反序列化漏洞的示例分析”這篇文章就分享到這里了,希望以上內容可以對大家有一定的幫助,讓大家可以學到更多知識,如果覺得文章不錯,可以把它分享出去讓更多的人看到吧!
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。