激情久久久_欧美视频区_成人av免费_不卡视频一二三区_欧美精品在欧美一区二区少妇_欧美一区二区三区的

服務器之家:專注于服務器技術及軟件下載分享
分類導航

PHP教程|ASP.NET教程|Java教程|ASP教程|編程技術|正則表達式|C/C++|IOS|C#|Swift|Android|VB|R語言|JavaScript|易語言|vb.net|

服務器之家 - 編程語言 - Java教程 - java安全編碼指南之:對象構建操作

java安全編碼指南之:對象構建操作

2020-09-15 01:02flydean程序那些事 Java教程

這篇文章主要介紹了java安全編碼指南之:對象構建操作,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧

簡介

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

構造函數的異常

考慮下面的一個例子:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
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。

看下調用的例子:

?
1
2
3
4
public static void main(String[] args) {
  SensitiveOperation sensitiveOperation = new SensitiveOperation();
  sensitiveOperation.storeMoney();
}

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

?
1
2
3
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方法中繞過安全檢查呢?

看下面的例子:

?
1
2
3
4
5
6
7
8
9
10
11
12
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。看下運行的代碼:

?
1
2
3
4
5
6
7
8
9
10
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);
}

運行結果:

?
1
2
3
Security check failed!
We can still do store Money action!
Store 1000000 RMB!

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

這個操作就叫做Finalizer Attack。

解決Finalizer Attack

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

使用final class

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

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
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,也可以解決這個問題。

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
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變量,這樣也可以避免之前提到的問題:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
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方法:

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
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安全編碼指南之:對象構建操作就是小編分享給大家的全部內容了,希望能給大家一個參考,也希望大家多多支持服務器之家。

原文鏈接:https://blog.csdn.net/superfjj/article/details/108334341

延伸 · 閱讀

精彩推薦
主站蜘蛛池模板: 鲁丝片一区二区三区免费入口 | 午夜视频在线在免费 | 午夜国产福利 | 欧美一级爱操视频 | 亚洲一区二区三区精品在线观看 | 日本一区二区不卡在线观看 | 久久久久国产成人免费精品免费 | 黄色高清免费网站 | 久久久青青草 | 一级成人免费 | 极色品影院 | 日韩黄色av网站 | 成人午夜在线播放 | 国产精品区一区二区三区 | 一区二区三区视频在线 | 超碰人人射 | 精品一区二区三区日本 | 国产一区二区三区视频观看 | 国产91精品久久久 | 羞羞视频.www在线观看 | 羞羞视频一区二区 | 看国产精品 | 欧美精品久久久久久久久老牛影院 | www深夜成人 | 91美女视频在线 | 91高清免费观看 | 日韩视频高清 | 免费国产一级淫片 | 牛牛碰在线| 欧美在线 | 亚洲 | 在线视频国产一区 | 91免费版在线 | 黄色大片在线免费看 | 斗罗破苍穹在线观看免费完整观看 | 久久99精品国产99久久6男男 | 久久精品视频网址 | 亚洲成人在线免费观看 | 久久蜜臀一区二区三区av | 久久国产成人午夜av浪潮 | 性插视频 | 欧美成人一区二区视频 |