★ Java代碼說明:
f.setAccessible(true):1、提高性能2、訪問私有private變量的時候
Accessable屬性是繼承自AccessibleObject 類. 功能是啟用或禁用安全檢查 (實際上setAccessible是啟用和禁用訪問安全檢查的開關,並不是為true就能訪問為false就不能訪問的意思 )。
A、提高性能
由於JDK的安全檢查耗時較多.所以通過setAccessible(true)的方式關閉安全檢查就可以達到提升反射速度的目的 。使用了method.setAccessible(true)后,性能有了20倍的提升。
B、訪問私有private變量的時候
java代碼中,常常將一個類的成員變量置為private,在類的外面獲取此類的私有成員變量的value時,需要注意setAccessible(true),否則或報錯:can not access a member of.......
一般情況下,我們並不能對類的私有字段進行操作,利用反射也不例外,但有的時候,例如要序列化的時候,我們又必須有能力去處理這些字段,這時候,我們就需要調用AccessibleObject上的setAccessible()方法來允許這種訪問,而由於反射類中的Field,Method和Constructor繼承自AccessibleObject,因此,通過在這些類上調用setAccessible()方法,我們可以實現對這些字段的操作。
代碼示例:
Class cls = object.getClass(); Field[] fields = cls.getDeclaredFields(); //getDeclaredFields()返回Class中所有的字段,包括私有字段。//getFields 只返回公共字段,即有public修飾的字段。 for (Field field : fields) { field.setAccessible(true); map.put(field.getName(), field.get(object)); }
★ 代碼審計 解釋說明:
JDK API中的解釋 :
1、AccessibleObject 類是 Field、Method 和 Constructor 對象的基類。它提供了將反射的對象標記為在使用時取消默認 Java 語言訪問控制檢查的能力。
2、對於公共成員、默認(打包)訪問成員、受保護成員和私有成員,在分別使用 Field、Method 或 Constructor 對象來設置或獲得字段、調用方法,或者創建和初始化類的新實例的時候,會執行訪問檢查。
AccessibleObject類 允許程序員繞過 由Java訪問說明符提供的 訪問控制(access control)檢查,特別是他讓程序員能夠允許 反射對象繞過 Java access control,並反過來更改私有字段或調用私有方法、行為,這些通常情況下都是不允許的。
個人覺得只要Field.setAccessible(true)之后,Class中所有的字段,包括私有字段也可以有訪問權限,這樣的反射會改變JAVA的結構,
甚至你的代碼可維護性,你完全可以 改別的代碼里面的值 ,所以通過反射能做一些讓你無法想象的東西。最好可以避免這樣的設置,以增強代碼的安全性,減少其脆弱性及缺陷。
★ 修復建議:
只能使用攻擊者無法設置的參數,通過有權限的類更改訪問說明符。所有出現的訪問說明符都應該仔細檢查。
————————————————
參考文章:
https://www.cnblogs.com/fanguangdexiaoyuer/p/6548171.html
https://blog.csdn.net/kjfcpua/article/details/8496911