日本综合一区二区|亚洲中文天堂综合|日韩欧美自拍一区|男女精品天堂一区|欧美自拍第6页亚洲成人精品一区|亚洲黄色天堂一区二区成人|超碰91偷拍第一页|日韩av夜夜嗨中文字幕|久久蜜综合视频官网|精美人妻一区二区三区

RELATEED CONSULTING
相關(guān)咨詢
選擇下列產(chǎn)品馬上在線溝通
服務(wù)時(shí)間:8:30-17:00
你可能遇到了下面的問題
關(guān)閉右側(cè)工具欄

新聞中心

這里有您想知道的互聯(lián)網(wǎng)營銷解決方案
Java安全基礎(chǔ)之Java的反射機(jī)制

好長時(shí)間沒有更新了,今天更新一篇關(guān)于java反射機(jī)制的文章,初學(xué)Java安全,內(nèi)容如有不恰當(dāng)?shù)牡胤剑€請(qǐng)各位大佬指正。

在梅里斯等地區(qū),都構(gòu)建了全面的區(qū)域性戰(zhàn)略布局,加強(qiáng)發(fā)展的系統(tǒng)性、市場(chǎng)前瞻性、產(chǎn)品創(chuàng)新能力,以專注、極致的服務(wù)理念,為客戶提供做網(wǎng)站、成都網(wǎng)站設(shè)計(jì) 網(wǎng)站設(shè)計(jì)制作按需定制,公司網(wǎng)站建設(shè),企業(yè)網(wǎng)站建設(shè),品牌網(wǎng)站設(shè)計(jì),全網(wǎng)營銷推廣,外貿(mào)網(wǎng)站制作,梅里斯網(wǎng)站建設(shè)費(fèi)用合理。

一、什么是反射

反射(Reflection)是Java的特征之一,C/C++語言中不存在反射,反射的存在使得運(yùn)行中的Java程序能夠獲取自身的信息,并且可以操作類或?qū)ο蟮膬?nèi)部屬性。那什么是反射呢?

下面是官方的解釋:

反射使得Java代碼能夠發(fā)現(xiàn)有已加載類的字段、方法和構(gòu)造函數(shù)的信息,并在安全限制內(nèi)使用反射的字段、方法和構(gòu)造函數(shù)對(duì)其底層對(duì)應(yīng)的對(duì)象進(jìn)行操作

簡(jiǎn)單來說,通過反射,我們可以在運(yùn)行時(shí)獲得程序或程序集中每一個(gè)類型的成員和成員的信息。同樣的,Java的反射機(jī)制也是也是如此,在運(yùn)行狀態(tài)中,通過Java的反射機(jī)制,我們能夠判斷一個(gè)對(duì)象所屬的類;了解任意一個(gè)類的所有屬性和方法;能夠調(diào)用任意一個(gè)對(duì)象的任意方法和屬性;這種動(dòng)態(tài)獲取的信息以及動(dòng)態(tài)調(diào)用對(duì)象的方法的功能稱為Java語言的反射機(jī)制。

二、反射的用途

在靜態(tài)語言中,一般對(duì)象的類型都是在編譯期就確定下來的,二通過Java反射機(jī)制,可以動(dòng)態(tài)的創(chuàng)建對(duì)象并調(diào)用其方法或?qū)傩?,這也就使得的反射的用途很廣泛,在開發(fā)過程中使用Eclipse、IDEA等開發(fā)工具時(shí),當(dāng)我們輸入一個(gè)對(duì)象或類并想調(diào)用它的屬性或方法時(shí),編譯器會(huì)自動(dòng)列出它的屬性或方法,這是通過反射實(shí)現(xiàn)的;載入,JavaBean和jsp之間的調(diào)用也是通過反射實(shí)現(xiàn)的。反射最重要的用途是開發(fā)各種框架,如上文中提到的Spring框架以及ORM框架,都是通過反射機(jī)制來實(shí)現(xiàn)的。

面向不同的用戶,反射機(jī)制的重要程度也大不相同。對(duì)于框架開發(fā)人員來說,反射雖小但作用非常大,它是各種容器實(shí)現(xiàn)的核心。對(duì)于一般的開發(fā)者來說,反射的作用相對(duì)較小。但總體來說,適當(dāng)了解二框架的底層機(jī)制對(duì)我們的編程思想也是非常有幫助的。

三、靜態(tài)語言和動(dòng)態(tài)語言

在學(xué)習(xí)反射之前,我們有必要了解一下什么是動(dòng)態(tài)語言和靜態(tài)語言

  • 靜態(tài)語言(強(qiáng)類型語言)

靜態(tài)語言是在編譯時(shí)變量的數(shù)據(jù)類型即可確定的語言,多數(shù)靜態(tài)語言要求在使用變量之前必須聲明數(shù)據(jù)的類型。如C++、Java、Delphi、C#等

  • 動(dòng)態(tài)語言(弱類型語言)

動(dòng)態(tài)語言時(shí)在運(yùn)行是確定數(shù)據(jù)類型的語言。變量使用之前不需要類型聲明,通常變量的類型是被賦值的那個(gè)值的類型。如PHP/ASP/Ruby/Python.Perl/ABAP/SQL/JavaScript/Unix Shell等等。

可以在程序運(yùn)行時(shí)改變程序結(jié)構(gòu)和變量類型的語言,比如在程序運(yùn)行時(shí),新的類和對(duì)象可以被加載和創(chuàng)建,新的函數(shù)或方法可以被加入或者去除等等。

3.1、動(dòng)態(tài)特性

動(dòng)態(tài)語言具有的某些特性即為動(dòng)態(tài)特性

以PHP舉例,一段代碼,其中變量值的改變可鞥導(dǎo)致這段代碼發(fā)生功能上的變化,我們將這種現(xiàn)象稱為PHP的動(dòng)態(tài)特性

比如下面的這個(gè)例子

我們只有當(dāng)代碼運(yùn)行時(shí),通過變量傳入的值才能確定其具體功能

3.2、動(dòng)態(tài)特性與Java反射

正是因?yàn)镻HP中存在多種動(dòng)態(tài)特性,使得開發(fā)人員能通過很少的代碼實(shí)現(xiàn)非常多的功能,比較經(jīng)典的例子就是一句話木馬,通過一行

但是Java本身是一門靜態(tài)語言,無法像PHP那么靈活多變。但是通過Java反射機(jī)制,可以為自身提供一些動(dòng)態(tài)特性。比如,當(dāng)我們通過IDE寫代碼時(shí),敲擊點(diǎn)好號(hào)“.”,會(huì)出現(xiàn)當(dāng)前對(duì)象或類所包含的屬性和方法,這里用到的就是Java反射機(jī)制。

反射最重要的用途就是開發(fā)各種通用框架,很多框架嗾使通過XML文件來進(jìn)行配置的(如:struts.xml,spring-*.xml等),即所謂的框架核心配置文件。為了確??蚣艿耐ㄓ眯?,程序運(yùn)行時(shí)需要根據(jù)配置文件中對(duì)應(yīng)的內(nèi)容加載不同的類或?qū)ο螅{(diào)用不同的方法,這也依賴于Java反射機(jī)制。

3.3、Java反射機(jī)制功能點(diǎn)

綜上所述,Java反射機(jī)制的功能可分為如下幾點(diǎn):

  • 在程序運(yùn)行時(shí)查找一個(gè)對(duì)象所屬的類
  • 在程序運(yùn)行時(shí)查找任意一個(gè)類的成員變量和方法
  • 在程序運(yùn)行時(shí)構(gòu)造任意一個(gè)類的對(duì)象
  • 在程序運(yùn)行時(shí)調(diào)用任意一個(gè)對(duì)象的方法

四、Java的命令執(zhí)行類

4.1、java.lang.Runtime類

這個(gè)類是一個(gè)共有類,每個(gè)Java應(yīng)用程序都有一個(gè)Runtime類實(shí)例,它允許應(yīng)用程序與運(yùn)行應(yīng)用程序的環(huán)境交互。當(dāng)前運(yùn)行時(shí)可以從getRuntime方法獲得。應(yīng)用程序無法創(chuàng)建自己的此類實(shí)例。

該類的主要方法是:getRuntime(),得到一個(gè)和當(dāng)前程序相關(guān)聯(lián)的Runtime類的對(duì)象,解釋如下:

返回與當(dāng)前Java應(yīng)用關(guān)聯(lián)的runtime對(duì)象。大多數(shù)Runtime類的方法是實(shí)例方法,所以必須被當(dāng)前運(yùn)行時(shí)對(duì)象調(diào)用。

Runtime對(duì)象可以調(diào)用exec()方法執(zhí)行命令,詳細(xì)文檔解釋如下:

在一個(gè)單獨(dú)的進(jìn)程中執(zhí)行指定的命令。這是一個(gè)方便的方法。以exec(command)形式調(diào)用與exec(String,Stringp[],file)的表現(xiàn)是相同的。

下面是一段代碼示例:

五、獲取類對(duì)象

獲取類對(duì)象的方式有很多種,這里提供四種方式

  • forName()
  • 直接獲取
  • getClass()
  • getSystemClassLoader().loadClass()

5.1、獲取類對(duì)象-forName()

如果要使用Class類中的方法完成,就需要使用forName方法,只要有類名稱即可,更為防爆,擴(kuò)展性更強(qiáng)。這種方法并不陌生,在配置JDBC的時(shí)候,我們通常采用這種方法

5.2、獲取類對(duì)象-直接獲取

任何數(shù)據(jù)類型都具備一個(gè)靜態(tài)的屬性,可以使用.class來獲取其對(duì)應(yīng)的Class對(duì)象。這種方法相對(duì)簡(jiǎn)單,但還是要明確用到類的靜態(tài)成員

5.3、獲取類對(duì)象-getClass()

我們可以通過Object類中的getClass()方法來獲取字節(jié)碼對(duì)象,不過這種方式較為繁瑣,必須要明確具體的類,然后創(chuàng)建對(duì)象

六、獲取類方法

獲取某個(gè)Class對(duì)象的方法集合,主要有以下幾種方法:

  • getDeclareMethods
  • getDecleardMethod
  • getMethods
  • getMethod

6.1、獲取類方法-getDeclaredMethods

getDeclaredMethods方法返回類或接口聲明的所有方法,包括:public、protected、private和默認(rèn)方法,但不包括繼承的方法

6.2、獲取類方法-getMethods

getMethods方法返回某個(gè)類的所有public方法,包括其繼承的public方法

6.3、獲取類方法-getMethod

getMethod方法只能返回一個(gè)特定的方法,如 Runtime類中的exec()方法,該方法的第一個(gè)參數(shù)為方法名稱,后面的參數(shù)為方法的參數(shù)對(duì)應(yīng)Class的對(duì)象

6.4、獲取類方法 - getDeclaredMethod

getDeclaredMethod方法與getMethod類似,也只能返回一個(gè)特定的方法,該方法的第一個(gè)參數(shù)為方法名,第二個(gè)參數(shù)名是方法參數(shù)

七、獲取類成員變量

為了更直觀地體現(xiàn)出獲取類成員變量的方法,我們首先創(chuàng)建一個(gè)Student類,要獲取Student類成員變量,主要有以下幾個(gè)方法:

  • getDeclaredFields
  • getDeclaredField
  • getFields
  • getField

7.1、獲取類成員變量-getDeclaredFields

getDeclaredFields方法能夠獲得類成員變量數(shù)組,包括public、private和proteced,但是不包括父類的聲明字段

7.2、獲取類成員變量-getFields

gteFields能夠獲得某個(gè)類的所有的public字段,包括父類中的字段

7.3、獲取類成員變量-getDeclaredField

該方法與getDeclaresFields的區(qū)別是只能獲得類的單個(gè)成員變量

7.4、獲取類成員變量-getField

與getFields類似,getField方法能夠獲得某個(gè)類特定的public字段,包括父類中的字段

八、構(gòu)造任意類的對(duì)象

構(gòu)造任意類的對(duì)象最經(jīng)典的方式:

無參數(shù):className.newInstance()

有參數(shù):getConstructor().newInstance()

構(gòu)造任意類的對(duì)象兩種方式異同

(1)首先兩種方式在原始碼所在的位置上不同

  • Class.newInstance() → 在java.lang包
  • Constructor.newInstance() → 在java.lang.reflect包

(2)在使用方法上的不同

  • ClassName.newInstance():
- Class.forName("com.ms08067.newInstance.newInstanceExample").newInstance();

- newInstanceExample.class.newInstance();
  • getConstructor().newInstance()
- newInstanceExample.class.getConstructor().newInstance();
  • Class.newInstance() 只能反射無參的構(gòu)造器
  • Constructor.newInstance() 可以反射任何構(gòu)造器
  • Class.newInstance() 需要構(gòu)造器可見
  • Constructor.newInstance() 可以反私有構(gòu)造器
  • Class.newInstance() 對(duì)于捕獲或者未捕獲的一場(chǎng)均由構(gòu)造器丟擲;
  • Constructor.newInstance() 通常會(huì)把丟擲的異常封裝成InvocationTrageException丟擲

九、調(diào)用任意實(shí)例對(duì)象的方法

調(diào)用任意實(shí)例對(duì)象的方法最經(jīng)典的方式

  • 直接調(diào)用:objectName.functionName()
  • invoke調(diào)用:invoke()

invoke方法調(diào)用任意實(shí)例對(duì)象是通過反射實(shí)現(xiàn)的,下面是一個(gè)示例:

十、不安全的反射

如前所述,利用Java的反射機(jī)制,我們可以無視類方法、變量訪問權(quán)限修飾符,調(diào)用任何類的任意方法、訪問并修改成員變量值,但是這樣做可能導(dǎo)致安全問題,如果一個(gè)攻擊者能夠通過應(yīng)用程序創(chuàng)建意外的控制流路徑,就有可能繞過安全檢查發(fā)起相關(guān)攻擊。假設(shè)有一段代碼如下:

其中存在一個(gè)字段name,當(dāng)獲取用戶請(qǐng)求的name字段后進(jìn)行判斷,如果請(qǐng)求的是Delect操作,則執(zhí)行DelectCommand函數(shù);若執(zhí)行的是Add操作,則執(zhí)行AddCommand函數(shù);如果不是這兩種操作,則執(zhí)行其他代碼。

假如開發(fā)者看到了這段代碼,他認(rèn)為可以使用Java的反射來重構(gòu)此代碼以減少代碼行,如下所示:

這樣的重構(gòu)看起來使得代碼行減少,消除了if/else塊,而且可以在不修改命令分派器的情況下添加新的命令類型,但是如果沒有對(duì)傳入的name字段進(jìn)行限制,則可以實(shí)例化實(shí)現(xiàn)Command接口的任何對(duì)象,從而導(dǎo)致安全問題。實(shí)際上,攻擊者甚至不局限于本例中的Command接對(duì)象,而是使用任何其他對(duì)象來實(shí)現(xiàn),如調(diào)用系統(tǒng)中任何對(duì)象的默認(rèn)構(gòu)造函數(shù),或者調(diào)用Runtime對(duì)象去執(zhí)行系統(tǒng)命令,這可能導(dǎo)致遠(yuǎn)程命令執(zhí)行漏洞,因此不安全的反射的危害性極大,也是我們審計(jì)過程中需要重點(diǎn)關(guān)注的內(nèi)容。


本文標(biāo)題:Java安全基礎(chǔ)之Java的反射機(jī)制
轉(zhuǎn)載源于:http://www.dlmjj.cn/article/djohdhp.html