中文字幕av专区_日韩电影在线播放_精品国产精品久久一区免费式_av在线免费观看网站

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

帶你了解java安全編碼中的對象構建

發布時間:2020-11-03 18:46:22 來源:億速云 閱讀:133 作者:Leah 欄目:開發技術

這篇文章運用簡單易懂的例子給大家介紹帶你了解java安全編碼中的對象構建,內容非常詳細,感興趣的小伙伴們可以參考借鑒,希望對大家能有所幫助。

構造函數的異常

考慮下面的一個例子:

public class SensitiveOperation {

  public SensitiveOperation(){
    if(!doSecurityCheck()){
      throw new SecurityException("Security check failed!");
    }
  }

  //Security check return false
  private boolean doSecurityCheck(){
    return false;
  }

  public void storeMoney(){
    System.out.println("Store 1000000 RMB!");
  }
}

上面的例子中,我們在構造函數中做了一個securityCheck,因為這個securityCheck返回的值是false,所以會拋出SecurityException。

看下調用的例子:

  public static void main(String[] args) {
    SensitiveOperation sensitiveOperation = new SensitiveOperation();
    sensitiveOperation.storeMoney();
  }

這個調用會拋出下面的異常:

Exception in thread "main" java.lang.SecurityException: Security check failed!
 at com.flydean.SensitiveOperation.<init>(SensitiveOperation.java:11)
 at com.flydean.SensitiveUsage.main(SensitiveUsage.java:10)

那么問題來了,上面的這個class是不是安全的呢?

Finalizer Attack

上面的class不是final的,所以我們可以構造一個class去繼承它。然后考慮這樣一個問題,當構造函數拋出異常之后,會執行什么操作呢?

如果該對象已經被構建了,那么這個對象在GC的時候需要執行finalize方法。那么我們是不是可以在finalize方法中繞過安全檢查呢?

看下面的例子:

public class SensitiveOperationFinalizer extends SensitiveOperation{

  public SensitiveOperationFinalizer(){
  }

  @Override
  protected void finalize() {
    System.out.println("We can still do store Money action!");
    this.storeMoney();
    System.exit(0);
  }
}

上的例子中,我們繼承了SensitiveOperation,并且實現了finalize方法,在finalize中,我們調用了storeMoney。看下運行的代碼:

  public void testFinalizer() throws InterruptedException {
    try {
    SensitiveOperation sensitiveOperation = new SensitiveOperationFinalizer();
      sensitiveOperation.storeMoney();
    }catch (Exception e){
      System.out.println(e.getMessage());
    }
    System.gc();
    Thread.sleep(10000);
  }

運行結果:

Security check failed!
We can still do store Money action!
Store 1000000 RMB!

可以看到,雖然我們構造函數拋出了異常,但是storeMoney的操作還是被執行了!

這個操作就叫做Finalizer Attack。

解決Finalizer Attack

怎么解決這個構造函數拋出異常的問題呢?這里給大家介紹幾種解決方法。

使用final class

如果使用final class,那么類是不能夠被繼承的,問題自然就解決了。

public final class SensitiveOperationFinal {

  public SensitiveOperationFinal(){
    if(!doSecurityCheck()){
      throw new SecurityException("Security check failed!");
    }
  }

  //Security check return false
  private boolean doSecurityCheck(){
    return false;
  }

  public void storeMoney(){
    System.out.println("Store 1000000 RMB!");
  }
}

使用final finalize方法

因為子類想要重寫finalize方法,如果我們的父類中finalize方法定義為final,也可以解決這個問題。

public final class SensitiveOperationFinal {

  public SensitiveOperationFinal(){
    if(!doSecurityCheck()){
      throw new SecurityException("Security check failed!");
    }
  }

  //Security check return false
  private boolean doSecurityCheck(){
    return false;
  }

  public void storeMoney(){
    System.out.println("Store 1000000 RMB!");
  }
  
  final protected void finalize() {
  }
}

使用flag變量

我們可以在對象構建完畢的時候設置一個flag變量,然后在每次安全操作的時候都去判斷一下這個flag變量,這樣也可以避免之前提到的問題:

public class SensitiveOperationFlag {

  private volatile boolean flag= false;

  public SensitiveOperationFlag(){
    if(!doSecurityCheck()){
      throw new SecurityException("Security check failed!");
    }
    flag=true;
  }

  //Security check return false
  private boolean doSecurityCheck(){
    return false;
  }

  public void storeMoney(){
    if(!flag){
      System.out.println("Object is not initiated yet!");
      return;
    }
    System.out.println("Store 1000000 RMB!");
  }
}

注意,這里flag需要設置為volatile,只有這樣才能保證構造函數在flag設置之前執行。也就是說需要保證happens-before特性。

使用this或者super

在JDK6或者更高版本中,如果對象的構造函數在java.lang.Object構造函數退出之前引發異常,則JVM將不會執行該對象的finalize方法。

因為Java確保java.lang.Object構造函數在任何構造函數的第一條語句之上或之前執行。如果構造函數中的第一個語句是對超類的構造函數或同一個類中的另一個構造函數的調用,則java.lang.Object構造函數將在該調用中的某個位置執行。否則,Java將在該構造函數的代碼中的任何一個執行之前執行超類的默認構造函數,并且將通過隱式調用執行java.lang.Object構造函數。

也就是說如果異常發生在構造函數中的第一條this或者super中的時候,JVM將不會調用對象的finalize方法:

public class SensitiveOperationThis {

  public SensitiveOperationThis(){
    this(doSecurityCheck());
  }

  private SensitiveOperationThis(boolean secure) {
  }

  //Security check return false
  private static boolean doSecurityCheck(){
     throw new SecurityException("Security check failed!");
  }

  public void storeMoney(){
    System.out.println("Store 1000000 RMB!");
  }
}

關于帶你了解java安全編碼中的對象構建就分享到這里了,希望以上內容可以對大家有一定的幫助,可以學到更多知識。如果覺得文章不錯,可以把它分享出去讓更多的人看到。

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

壤塘县| 牙克石市| 建平县| 墨竹工卡县| 房产| 吴桥县| 论坛| 六安市| 金昌市| 扎鲁特旗| 巴林左旗| 马龙县| 盐山县| 石河子市| 莱西市| 平山县| 龙门县| 墨江| 鞍山市| 始兴县| 永年县| 芜湖县| 新野县| 周口市| 邹城市| 分宜县| 洛宁县| 佳木斯市| 德兴市| 慈溪市| 永宁县| 府谷县| 龙山县| 赞皇县| 嘉禾县| 达拉特旗| 江津市| 阿拉善盟| 东源县| 都兰县| 固阳县|