ABAP和Java裏的單例模式攻擊

面向對象編程世界裏的單例模式(Singleton)多是設計模式裏最簡單的一種,大多數開發人員都以爲能夠很容易掌握它的用法。單例模式保證一個類僅有一個實例,並提供一個訪問它的全局訪問點。java

然而在某些場景下,這種設計模式的單例特性會被破壞,看下面這個例子:編程

clipboard1,1

代碼的第三行,這個ABAP類實現了接口if_serializable_object,這意味着它能夠被關鍵字CALL TRANSFORMATION進行序列化和反序列化操做。設計模式

使用下面的ABAP代碼:this

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.

clipboard2,2

執行以後,在調試器裏發現lo_instance和lo_instance2指向了兩個不一樣的對象實例,說明此時這個ABAP單例模式已經被破壞了。設計

clipboard3,3

再看看Java,下面是一個最簡單的Java單例模式:3d

clipboard4,4

然而咱們仍然能夠經過Java的反射機制來破壞這個單例:調試

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);

clipboard5,5

在Java裏,咱們能夠經過枚舉類來防護這種反射攻擊:code

public enum JerrySingletonAnotherApproach {
  INSTANCE ;  
  
  private String name = "Jerry" ;
   
  public String getName() {  
      return this.name;  
  }  
}

clipboard6,6

這種單例模式的消費代碼:對象

System.out.println("Name:" + JerrySingletonAnotherApproach.INSTANCE.getName());

此時別有用心的攻擊者若是想使用反射機制建立新的實例,會收到下面的報錯信息:blog

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)

要獲取更多Jerry的原創文章,請關注公衆號"汪子熙": 公衆號截圖

相關文章
相關標籤/搜索