這篇文章主要介紹“Java單例模式的攻擊與防御怎么理解”,在日常操作中,相信很多人在Java單例模式的攻擊與防御怎么理解問題上存在疑惑,小編查閱了各式資料,整理出簡單好用的操作方法,希望對大家解答”Java單例模式的攻擊與防御怎么理解”的疑惑有所幫助!接下來,請跟著小編一起來學(xué)習(xí)吧!
創(chuàng)新互聯(lián)是一家從事企業(yè)網(wǎng)站建設(shè)、網(wǎng)站制作、成都網(wǎng)站制作、行業(yè)門戶網(wǎng)站建設(shè)、網(wǎng)頁設(shè)計(jì)制作的專業(yè)網(wǎng)絡(luò)公司,擁有經(jīng)驗(yàn)豐富的網(wǎng)站建設(shè)工程師和網(wǎng)頁設(shè)計(jì)人員,具備各種規(guī)模與類型網(wǎng)站建設(shè)的實(shí)力,在網(wǎng)站建設(shè)領(lǐng)域樹立了自己獨(dú)特的設(shè)計(jì)風(fēng)格。自公司成立以來曾獨(dú)立設(shè)計(jì)制作的站點(diǎn)超過千家。說到“單例模式被攻擊”這個話題,大家最容易想到的可能就是通過序列化/反序列化來攻擊單例模式,因?yàn)橐粋€對象實(shí)例序列化再反序列化后,得到的新的對象雖然各字段內(nèi)容和原字段一致,然而對象地址和原始對象地址相比已經(jīng)發(fā)生了變化,因此它們是兩個不同的對象。
上面的結(jié)論完全正確,然而除了序列化/反序列化,單例模式還可能遭受另一種方式的攻擊,即反射攻擊(Reflection attack)。
看一個具體例子:
public class JerrySingleton { private String name; private JerrySingleton(){ name = "Jerry"; }private static class SingletonHolder{ private static final JerrySingleton INSTANCE = new JerrySingleton(); }public static JerrySingleton getInstance() { return SingletonHolder.INSTANCE; } }
上面是一個餓漢式單例。
然而我只需要將這個單例類JerrySingleton的構(gòu)造函數(shù)通過反射設(shè)置成可以訪問Accessible,然后就能通過反射調(diào)用該構(gòu)造函數(shù),進(jìn)而生成新的對象實(shí)例。這樣就破壞了單例模式。
Class<?> classType = JerrySingleton.class; Constructor<?> c = classType.getDeclaredConstructor(null); c.setAccessible(true); JerrySingleton e1 = (JerrySingleton)c.newInstance(); JerrySingleton e2 = JerrySingleton.getInstance(); System.out.println(e1 == e2);
第6行代碼會打印false。
針對這種攻擊,一種可行的防御措施是在單例類的構(gòu)造函數(shù)內(nèi)定義一個布爾變量,初始化為false。當(dāng)構(gòu)造函數(shù)執(zhí)行后,該變量被置為true。如果接下來構(gòu)造函數(shù)再次被執(zhí)行,則人為拋出異常,避免構(gòu)造函數(shù)重復(fù)執(zhí)行。
public class JerrySingletonImproved { private static boolean flag = false; private JerrySingletonImproved(){ synchronized(JerrySingletonImproved.class) { if(flag == false) { flag = !flag; } else { throw new RuntimeException("Singleton violated"); } } } }
這種防御措施無法從根本上杜絕Singleton被攻擊,因?yàn)楣粽呷耘f可以通過反射來修改布爾變量flag的值,從而繞過這個檢查。
最理想的不會受到攻擊的單例模式實(shí)現(xiàn)是借助Java里枚舉類Enumeration的特性:
這種實(shí)現(xiàn)類型的單例模式的消費(fèi)代碼:
System.out.println("Name:" + JerrySingletonAnotherApproach.INSTANCE.getName());
如果攻擊者通過前面介紹的反射代碼對這種實(shí)現(xiàn)方式的單例進(jìn)行攻擊,JDK會拋出NoSuchMethodException異常:
Exception in thread "main" java.lang.NoSuchMethodException: singleton.JerrySingletonAnotherApproach.<init>() at java.lang.Class.getConstructor0(Class.java:3082) at java.lang.Class.getDeclaredConstructor(Class.java:2178) at singleton.SingletonAttack.test3(SingletonAttack.java:31) at singleton.SingletonAttack.main(SingletonAttack.java:43)
究其原因,是因?yàn)楝F(xiàn)在我們是通過Java枚舉方式實(shí)現(xiàn)的單例,枚舉類沒有傳統(tǒng)意義上的構(gòu)造函數(shù),因此對這種反射攻擊免疫。
到此,關(guān)于“Java單例模式的攻擊與防御怎么理解”的學(xué)習(xí)就結(jié)束了,希望能夠解決大家的疑惑。理論與實(shí)踐的搭配能更好的幫助大家學(xué)習(xí),快去試試吧!若想繼續(xù)學(xué)習(xí)更多相關(guān)知識,請繼續(xù)關(guān)注創(chuàng)新互聯(lián)-成都網(wǎng)站建設(shè)公司網(wǎng)站,小編會繼續(xù)努力為大家?guī)砀鄬?shí)用的文章!
當(dāng)前題目:Java單例模式的攻擊與防御怎么理解-創(chuàng)新互聯(lián)
當(dāng)前網(wǎng)址:http://jinyejixie.com/article30/djedso.html
成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供企業(yè)網(wǎng)站制作、動態(tài)網(wǎng)站、網(wǎng)站策劃、做網(wǎng)站、網(wǎng)頁設(shè)計(jì)公司、外貿(mào)建站
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請盡快告知,我們將會在第一時間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場,如需處理請聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時需注明來源: 創(chuàng)新互聯(lián)
猜你還喜歡下面的內(nèi)容