色综合图-色综合图片-色综合图片二区150p-色综合图区-玖玖国产精品视频-玖玖香蕉视频

您的位置:首頁技術(shù)文章
文章詳情頁

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

瀏覽:3日期:2022-08-24 17:39:27

簡介

mutable(可變)和immutable(不可變)對(duì)象是我們?cè)趈ava程序編寫的過程中經(jīng)常會(huì)使用到的。

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

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

雖然mutable對(duì)象安全性不夠,但是因?yàn)槠淇梢员恍薷模詴?huì)有效的減少對(duì)該對(duì)象的拷貝。

而immutable對(duì)象因?yàn)椴豢筛淖儯試L試對(duì)該對(duì)象的修改都會(huì)導(dǎo)致對(duì)象的拷貝,從而生成新的對(duì)象。

我們最常使用的String就是一個(gè)immutable對(duì)象。

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

可變對(duì)象和不可變對(duì)象

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

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

看一個(gè)例子java.util.Date是一個(gè)可變對(duì)象,而java.time.LocalTime是不可變對(duì)象。

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

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

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

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

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

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

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

public class Date

public final class LocalTime

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

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

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

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

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對(duì)象創(chuàng)建拷貝,那么相應(yīng)的mutable類也需要提供一個(gè)copy方法來協(xié)助拷貝。

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

不要相信equals

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

private final Map<Window,Extra> extras = new HashMap<>(); public void op(Window window) { Extra extra = extras.get(window); }

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

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

怎么解決這個(gè)問題呢?

Java中有一個(gè)特別的HashMap:IdentityHashMap,這個(gè)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可用,那么可以使用不可變對(duì)象作為key或者使用Window的私有變量,從而惡意攻擊者無法獲得這個(gè)變量。

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

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

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

如果直接暴露出去,那么基本上就沒有權(quán)限控制可言,任何程序只要能夠拿到你這個(gè)對(duì)象,就可以對(duì)屬性進(jìn)行修改。考慮下下面的應(yīng)用方式,我們?cè)谛薷膕tate的方法中加入了一個(gè)參數(shù)校驗(yàn)和權(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

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

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

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

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

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

其實(shí)不然,比如我們定義了一個(gè)final的List,雖然這個(gè)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)容了,希望能給大家一個(gè)參考,也希望大家多多支持好吧啦網(wǎng)。

標(biāo)簽: Java
相關(guān)文章:
主站蜘蛛池模板: 国产一级做a爰片在线看 | 亚洲一级毛片免观看 | 精品久久久久久 | 日韩一区二区在线观看 | 精品久久精品久久 | 女同日韩互慰互摸在线观看 | 亚洲欧美日韩国产vr在线观 | 性欧美视频a毛片在线播放 性欧美一级 | 亚洲综合免费视频 | 国产99视频精品免费观看9e | 国产精品久久久久精 | 爽死你个放荡粗暴小淫货双女视频 | 亚洲成人黄色在线观看 | 日日摸人人拍人人澡 | 欧美变态一级毛片 | 美女视频黄色网址 | 亚洲国产经典 | 精品视频免费在线 | 欧美成人性色生活片免费在线观看 | 男人一进一出桶女人视频 | 一区二区三区在线免费观看视频 | 欧美日韩精品免费一区二区三区 | 亚洲成网站 | 黄色福利网 | 13一14周岁毛片免费 | 偷柏自拍亚洲欧美综合在线图 | 色三级大全高清视频在线观看 | 99视频在线| 欧美性猛交xxxx免费看手交 | 亚洲一区二区三区在线视频 | 国产亚洲精品国看不卡 | 国产不卡a | 精品国产90后在线观看 | 欧美成人吃奶高清视频 | 日韩亚洲综合精品国产 | 亚洲女人被黑人猛躁进女人 | 一区二区国产在线播放 | 精品日韩一区二区三区 | 成人69视频在线观看免费 | 精品一久久 | 久久免费国产精品一区二区 |