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

java安全編碼指南之:Mutability可變性詳解

 更新時間:2020年09月14日 11:35:31   作者:flydean程序那些事  
這篇文章主要介紹了java安全編碼指南之:Mutability可變性詳解,具有很好的參考價值,希望對大家有所幫助。一起跟隨小編過來看看吧

簡介

mutable(可變)和immutable(不可變)對象是我們在java程序編寫的過程中經(jīng)常會使用到的。

可變類型對象就是說,對象在創(chuàng)建之后,其內(nèi)部的數(shù)據(jù)可能會被修改。所以它的安全性沒有保證。

而不可變類型對象就是說,對象一旦創(chuàng)建之后,其內(nèi)部的數(shù)據(jù)就不能夠被修改,我們可以完全相信這個對象。

雖然mutable對象安全性不夠,但是因為其可以被修改,所以會有效的減少對該對象的拷貝。

而immutable對象因為不可改變,所以嘗試對該對象的修改都會導(dǎo)致對象的拷貝,從而生成新的對象。

我們最常使用的String就是一個immutable對象。

那么可變性在java的安全編碼中的最佳實踐是怎么樣的呢? 一起來看看吧。

可變對象和不可變對象

知道了可變對象和不可變對象的不同之處之后,我們看一下怎么才能判斷這個對象是可變對象還是不可變對象呢?

首先,最簡單的一點就是,不可變對象創(chuàng)建之后就不能夠被修改,所以不可變對象里面基本上沒有setXXX之類的方法,而可變對象提供了setXXX這些可以修改內(nèi)部變量狀態(tài)的方法。

看一個例子java.util.Date是一個可變對象,而java.time.LocalTime是不可變對象。

看下他們的方法定義有什么區(qū)別呢?

首先是Date,我們可以看到在其中定義了很多setXXX方法。

而在LocalTime中,我們基本上看不到setXXX方法。

同時不可變對象的字段基本上都是final的,防止被二次修改。

第二,不可變對象一般來說是不可繼承的,在java中就是以final關(guān)鍵字做限定的:

public class Date

public final class LocalTime

第三,不可變對象一般會隱藏構(gòu)造函數(shù),而是使用類似工廠模式的方法來創(chuàng)建對象,這樣為實例的創(chuàng)建提供了更多的機動性。

創(chuàng)建mutable對象的拷貝

那么如果我們想使用mutable對象,又不想被別人修改怎么辦呢?

簡單的辦法就是拷貝一份要使用的對象:

public class CopyOutput {
      private final java.util.Date date;
      ...
      public java.util.Date getDate() {
        return (java.util.Date)date.clone();
      }
    }

這里大家還要注意深拷貝和淺拷貝的問題。

為mutable類創(chuàng)建copy方法

既然要為mutable對象創(chuàng)建拷貝,那么相應(yīng)的mutable類也需要提供一個copy方法來協(xié)助拷貝。

這里需要考慮一個深拷貝和淺拷貝的問題。

不要相信equals

我們知道在HashMap中怎么去查找一個key呢?先去找這個key的hash值,然后去判斷key.equals方法是否相等,考慮下面這種情況:

private final Map<Window,Extra> extras = new HashMap<>();

    public void op(Window window) {
      Extra extra = extras.get(window);
    }

op方法接收一個Window對象,然后將其當(dāng)成key從HashMap中取出對應(yīng)的value。

如果,這個時候,我們有一個類A繼承了Window,并且hash值和equals都和另外一個Window對象B相同,那么使用A這個key可以獲取到B這個key存儲的數(shù)據(jù)!

怎么解決這個問題呢?

Java中有一個特別的HashMap:IdentityHashMap,這個Map的key和value比較是用==而不是equals方法,所以可以有效的避免上面出現(xiàn)的問題。

private final Map<Window,Extra> extras = new IdentityHashMap<>();

    public void op(Window window) {
      Extra extra = extras.get(window);
    }

如果沒有這樣的Map可用,那么可以使用不可變對象作為key或者使用Window的私有變量,從而惡意攻擊者無法獲得這個變量。

public class Window {
      /* pp */ 
      class PrivateKey {
        Window getWindow() {
          return Window.this;
        }
      }
      final PrivateKey privateKey = new PrivateKey();

      private final Map<Window.PrivateKey,Extra> extras =
         new WeakHashMap<>();
      ...
    }

    public class WindowOps {
      public void op(Window window) {
        // Window.equals may be overridden,
        // but safe as we don't use it.
        Extra extra = extras.get(window.privateKey);
        ...
      }
    }

不要直接暴露可修改的屬性

如果一個可變類中的某個屬性確實需要暴露被外部使用,那么一定要將這個屬性定義為private,并且使用wrapper方法將其包裝起來。

如果直接暴露出去,那么基本上就沒有權(quán)限控制可言,任何程序只要能夠拿到你這個對象,就可以對屬性進行修改??紤]下下面的應(yīng)用方式,我們在修改state的方法中加入了一個參數(shù)校驗和權(quán)限控制。

public final class WrappedState {
      // private immutable object
      private String state;

      // wrapper method
      public String getState() {
        return state;
      }

      // wrapper method
      public void setState(final String newState) {
        this.state = requireValidation(newState);
      }

      private static String requireValidation(final String state) {
        if (...) {
          throw new IllegalArgumentException("...");
        }
        return state;
      }
    }

public static fields應(yīng)該被置位final

同樣的,如果你是一個類變量,當(dāng)然不希望這個變量會被任何人修改,那么需要將其置位final。

public class Files {
      public static final String separator = "/";
      public static final String pathSeparator = ":";
    }

public static final field 應(yīng)該是不可變的

如果類變量是public static final的,那么這個變量一定要是不可變的。

有人會問了,都定義成了final了,是不是就已經(jīng)不可變了?

其實不然,比如我們定義了一個final的List,雖然這個list不能變化,但是list里面的值是可以變化的。我們需要將可變變量修改為不可變變量,如下所示:

import static java.util.Arrays.asList;
    import static java.util.Collections.unmodifiableList;
    ...
    public static final List<String> names = unmodifiableList(asList(
      "Fred", "Jim", "Sheila"
    ));

如果使用JDK9中引入的of()或者ofEntries()方法,可以直接創(chuàng)建不可修改的集合:

public static final List
<String> names =
 List.of("Fred", "Jim", "Sheila");

以上這篇java安全編碼指南之:Mutability可變性詳解就是小編分享給大家的全部內(nèi)容了,希望能給大家一個參考,也希望大家多多支持腳本之家。

相關(guān)文章

  • SpringBoot AOP方式實現(xiàn)多數(shù)據(jù)源切換的方法

    SpringBoot AOP方式實現(xiàn)多數(shù)據(jù)源切換的方法

    本篇文章主要介紹了SpringBoot AOP方式實現(xiàn)多數(shù)據(jù)源切換的方法,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2018-03-03
  • JavaAgent的簡單例子

    JavaAgent的簡單例子

    這篇文章主要介紹了JavaAgent的簡單例子,對JavaAgent感興趣的同學(xué),可以參考下
    2021-04-04
  • 如何避免在Java?中使用雙括號初始化

    如何避免在Java?中使用雙括號初始化

    這篇文章主要介紹了如何避免在Java中使用雙括號初始化,本文通過實例代碼給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2023-07-07
  • Spring jndi數(shù)據(jù)源配置方法詳解

    Spring jndi數(shù)據(jù)源配置方法詳解

    這篇文章主要為大家詳細(xì)介紹了Spring jndi數(shù)據(jù)源的配置方法,具有一定的參考價值,感興趣的小伙伴們可以參考一下解
    2017-07-07
  • log4j2?xml配置文件屏蔽第三方依賴包的日志方式

    log4j2?xml配置文件屏蔽第三方依賴包的日志方式

    這篇文章主要介紹了log4j2?xml配置文件屏蔽第三方依賴包的日志方式,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教
    2024-04-04
  • 基于java中的PO VO DAO BO POJO(詳解)

    基于java中的PO VO DAO BO POJO(詳解)

    下面小編就為大家?guī)硪黄趈ava中的PO VO DAO BO POJO(詳解)。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2017-06-06
  • spring boot集成shiro詳細(xì)教程(小結(jié))

    spring boot集成shiro詳細(xì)教程(小結(jié))

    這篇文章主要介紹了spring boot 集成shiro詳細(xì)教程,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2018-01-01
  • mybatisPlus批量插入優(yōu)化加快性能

    mybatisPlus批量插入優(yōu)化加快性能

    這篇文章主要介紹了mybatisPlus批量插入優(yōu)化加快性能,本文給大家介紹的非常詳細(xì),對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下
    2023-12-12
  • SpringBoot 統(tǒng)一異常處理詳解

    SpringBoot 統(tǒng)一異常處理詳解

    這篇文章主要介紹了SpringBoot統(tǒng)一異常處理,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2019-05-05
  • SpringCloud集成Hystrix熔斷過程分步分解

    SpringCloud集成Hystrix熔斷過程分步分解

    通過hystrix可以解決雪崩效應(yīng)問題,它提供了資源隔離、降級機制、融斷、緩存等功能。接下來通過本文給大家分享SpringCloud集成Hystrix熔斷,感興趣的朋友一起看看吧
    2022-09-09

最新評論