欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

java安全編碼指南之:對象構(gòu)建操作

 更新時間:2020年09月14日 14:28:17   作者:flydean程序那些事  
這篇文章主要介紹了java安全編碼指南之:對象構(gòu)建操作,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧

簡介

程序員肯定是不缺對象的,因為隨時都可以構(gòu)建一個,對象多了肯定會出現(xiàn)點(diǎn)安全問題,一起來看看在java的對象構(gòu)建中怎么保證對象的安全性吧。

構(gòu)造函數(shù)的異常

考慮下面的一個例子:

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!");
  }
}

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

看下調(diào)用的例子:

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

這個調(diào)用會拋出下面的異常:

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的,所以我們可以構(gòu)造一個class去繼承它。然后考慮這樣一個問題,當(dāng)構(gòu)造函數(shù)拋出異常之后,會執(zhí)行什么操作呢?

如果該對象已經(jīng)被構(gòu)建了,那么這個對象在GC的時候需要執(zhí)行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,并且實現(xiàn)了finalize方法,在finalize中,我們調(diào)用了storeMoney??聪逻\(yùn)行的代碼:

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

運(yùn)行結(jié)果:

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

可以看到,雖然我們構(gòu)造函數(shù)拋出了異常,但是storeMoney的操作還是被執(zhí)行了!

這個操作就叫做Finalizer Attack。

解決Finalizer Attack

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

使用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變量

我們可以在對象構(gòu)建完畢的時候設(shè)置一個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需要設(shè)置為volatile,只有這樣才能保證構(gòu)造函數(shù)在flag設(shè)置之前執(zhí)行。也就是說需要保證happens-before特性。

使用this或者super

在JDK6或者更高版本中,如果對象的構(gòu)造函數(shù)在java.lang.Object構(gòu)造函數(shù)退出之前引發(fā)異常,則JVM將不會執(zhí)行該對象的finalize方法。

因為Java確保java.lang.Object構(gòu)造函數(shù)在任何構(gòu)造函數(shù)的第一條語句之上或之前執(zhí)行。如果構(gòu)造函數(shù)中的第一個語句是對超類的構(gòu)造函數(shù)或同一個類中的另一個構(gòu)造函數(shù)的調(diào)用,則java.lang.Object構(gòu)造函數(shù)將在該調(diào)用中的某個位置執(zhí)行。否則,Java將在該構(gòu)造函數(shù)的代碼中的任何一個執(zhí)行之前執(zhí)行超類的默認(rèn)構(gòu)造函數(shù),并且將通過隱式調(diào)用執(zhí)行java.lang.Object構(gòu)造函數(shù)。

也就是說如果異常發(fā)生在構(gòu)造函數(shù)中的第一條this或者super中的時候,JVM將不會調(diào)用對象的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!");
  }
}

本文的例子:

learn-java-base-9-to-20/tree/master/security

以上這篇java安全編碼指南之:對象構(gòu)建操作就是小編分享給大家的全部內(nèi)容了,希望能給大家一個參考,也希望大家多多支持腳本之家。

相關(guān)文章

  • SpringBoot實現(xiàn)阿里云快遞物流查詢的示例代碼

    SpringBoot實現(xiàn)阿里云快遞物流查詢的示例代碼

    本文將基于springboot實現(xiàn)快遞物流查詢,物流信息的獲取通過阿里云第三方實現(xiàn),具有一定的參考價值,感興趣的可以了解一下
    2021-10-10
  • Springboot允許logger.debug輸出日志方式

    Springboot允許logger.debug輸出日志方式

    這篇文章主要介紹了Springboot允許logger.debug輸出日志方式,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-06-06
  • Spring實戰(zhàn)之容器中的工程Bean用法示例

    Spring實戰(zhàn)之容器中的工程Bean用法示例

    這篇文章主要介紹了Spring實戰(zhàn)之容器中的工程Bean用法,結(jié)合實例形式分析了Sring框架容器中的工程Bean相關(guān)配置、使用操作技巧,需要的朋友可以參考下
    2019-11-11
  • java執(zhí)行windows下cmd命令的方法

    java執(zhí)行windows下cmd命令的方法

    這篇文章主要介紹了java執(zhí)行windows下cmd命令的方法,較為詳細(xì)的說明了Java執(zhí)行Windows下CMD命令的方法,并總結(jié)了常用的CMD命令供大家參考,需要的朋友可以參考下
    2014-11-11
  • Java中6種單例模式寫法代碼實例

    Java中6種單例模式寫法代碼實例

    這篇文章主要介紹了Java中6種單例模式寫法代碼實例,某個類任何情況下只有一個實例,并提供一個全局訪問點(diǎn)來獲取該實例,Java6種單例模式有2種懶漢式,2種餓漢式,靜態(tài)內(nèi)部類 ,枚舉類,需要的朋友可以參考下
    2024-01-01
  • 深入了解Spring Boot2.3.0及以上版本的Liveness和Readiness功能

    深入了解Spring Boot2.3.0及以上版本的Liveness和Readiness功能

    這篇文章主要介紹了Spring Boot2.3.0及以上版本的Liveness和Readiness功能示例深入解析,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-10-10
  • 解決Maven本地倉庫明明有對應(yīng)的jar包但還是報找不到的問題

    解決Maven本地倉庫明明有對應(yīng)的jar包但還是報找不到的問題

    這篇文章主要介紹了解決Maven本地倉庫明明有對應(yīng)的jar包但還是報找不到的問題,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-10-10
  • Springboot項目引入druid安裝部署使用教程

    Springboot項目引入druid安裝部署使用教程

    這篇文章主要介紹了Springboot項目引入druid安裝部署使用,本文通過實例代碼給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2022-01-01
  • 解析Java編程之Synchronized鎖住的對象

    解析Java編程之Synchronized鎖住的對象

    這篇文章主要介紹了解析Java編程之Synchronized鎖住的對象,具有一定參考價值,需要的朋友可以了解下。
    2017-10-10
  • JAVA拋出異常的三種形式詳解

    JAVA拋出異常的三種形式詳解

    這篇文章主要介紹了JAVA拋出異常的三種形式詳解,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下
    2019-07-07

最新評論