CLASS zcl_jerry_singleton DEFINITION PUBLIC FINAL CREATE PRIVATE . PUBLIC SECTION. INTERFACES if_serializable_object . CLASS-METHODS class_constructor . CLASS-METHODS get_instance RETURNING VALUE(ro_instance) TYPE REF TO zcl_jerry_singleton . PROTECTED SECTION. PRIVATE SECTION. CLASS-DATA so_instance TYPE REF TO zcl_jerry_singleton . DATA mv_name TYPE string . DATA mv_initialized TYPE abap_bool . METHODS constructor . ENDCLASS. CLASS ZCL_JERRY_SINGLETON IMPLEMENTATION. *---------------------------------------------------------------------------------------+ * | Static Public Method ZCL_JERRY_SINGLETON=>CLASS_CONSTRUCTOR * +-------------------------------------------------------------------------------------------------+ * +-------------------------------------------------------------------------------------- METHOD class_constructor. so_instance = NEW zcl_jerry_singleton( ). ENDMETHOD. *---------------------------------------------------------------------------------------+ * | Instance Public Method ZCL_JERRY_SINGLETON->CONSTRUCTOR * +-------------------------------------------------------------------------------------------------+ * +-------------------------------------------------------------------------------------- METHOD constructor. mv_name = 'Jerry'. IF mv_initialized = abap_false. mv_initialized = abap_true. ELSE. MESSAGE 'you are in trouble!' TYPE 'E' DISPLAY LIKE 'I'. ENDIF. ENDMETHOD. *---------------------------------------------------------------------------------------+ * | Static Public Method ZCL_JERRY_SINGLETON=>GET_INSTANCE * +-------------------------------------------------------------------------------------------------+ * | [<-()] RO_INSTANCE TYPE REF TO ZCL_JERRY_SINGLETON * +-------------------------------------------------------------------------------------- METHOD get_instance. ro_instance = so_instance. ENDMETHOD. ENDCLASS.
通過序列化/反序列化攻擊單例模式:
為南澳等地區(qū)用戶提供了全套網(wǎng)頁設(shè)計(jì)制作服務(wù),及南澳網(wǎng)站建設(shè)行業(yè)解決方案。主營業(yè)務(wù)為成都網(wǎng)站制作、成都網(wǎng)站建設(shè)、南澳網(wǎng)站設(shè)計(jì),以傳統(tǒng)方式定制建設(shè)網(wǎng)站,并提供域名空間備案等一條龍服務(wù),秉承以專業(yè)、用心的態(tài)度為用戶提供真誠的服務(wù)。我們深信只要達(dá)到每一位用戶的要求,就會得到認(rèn)可,從而選擇與我們長期合作。這樣,我們也可以走得更遠(yuǎn)!DATA(lo_instance) = zcl_jerry_singleton=>get_instance( ). DATA: s TYPE string.CALL TRANSFORMATION id SOURCE model = lo_instance RESULT XML s. DATA: lo_instance2 TYPE REF TO zcl_jerry_singleton.CALL TRANSFORMATION id SOURCE XML s RESULT model = lo_instance2.
繞過了單例的限制,構(gòu)造了第二個實(shí)例。
除了用序列化/反序列化攻擊外,還可以用反射攻擊。
然而我只需要將這個單例類JerrySingleton的構(gòu)造函數(shù)通過反射設(shè)置成可以訪問Accessible,然后就能通過反射調(diào)用該構(gòu)造函數(shù),進(jìn)而生成新的對象實(shí)例。這樣就破壞了單例模式。
第6行代碼會打印false。
針對這種攻擊,一種可行的防御措施是在單例類的構(gòu)造函數(shù)內(nèi)定義一個布爾變量,初始化為false。當(dāng)構(gòu)造函數(shù)執(zhí)行后,該變量被置為true。如果接下來構(gòu)造函數(shù)再次被執(zhí)行,則人為拋出異常,避免構(gòu)造函數(shù)重復(fù)執(zhí)行。
這種防御措施無法從根本上杜絕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異常:
究其原因,是因?yàn)楝F(xiàn)在我們是通過Java枚舉方式實(shí)現(xiàn)的單例,枚舉類沒有傳統(tǒng)意義上的構(gòu)造函數(shù),因此對這種反射攻擊免疫。
要獲取更多Jerry的原創(chuàng)文章,請關(guān)注公眾號"汪子熙":