明輝手游網(wǎng)中心:是一個(gè)免費(fèi)提供流行視頻軟件教程、在線學(xué)習(xí)分享的學(xué)習(xí)平臺(tái)!

Java體系結(jié)構(gòu)對(duì)信息安全的支持

[摘要]Java語(yǔ)言擁有三大特征:平臺(tái)無(wú)關(guān)性、網(wǎng)絡(luò)移動(dòng)性和安全性,而Java體系結(jié)構(gòu)對(duì)這三大特征提供了強(qiáng)大的支持和保證,本文著重介紹Java體系結(jié)構(gòu)對(duì)支持信息安全的原理和使用方法。   Java體系結(jié)構(gòu)   Java的體系結(jié)構(gòu)如下圖所示,首先Java的源代碼Java文件由編譯器編譯成Java的二進(jìn)制字節(jié)碼...

  Java語(yǔ)言擁有三大特征:平臺(tái)無(wú)關(guān)性、網(wǎng)絡(luò)移動(dòng)性和安全性,而Java體系結(jié)構(gòu)對(duì)這三大特征提供了強(qiáng)大的支持和保證,本文著重介紹Java體系結(jié)構(gòu)對(duì)支持信息安全的原理和使用方法。

  Java體系結(jié)構(gòu)

  Java的體系結(jié)構(gòu)如下圖所示,首先Java的源代碼Java文件由編譯器編譯成Java的二進(jìn)制字節(jié)碼class文件,然后class文件由Java虛擬機(jī)中的類裝載器進(jìn)行加載,同時(shí)類裝載器還會(huì)加載Java的原始 API Class文件,類加載器主要負(fù)責(zé)加載、連接和初始化這些class文件以后,就交給虛擬機(jī)中的執(zhí)行引擎運(yùn)行,執(zhí)行引擎將class文件中的Java指令解釋成具體的本地操作系統(tǒng)方法來(lái)執(zhí)行,而安全管理器將在執(zhí)行過(guò)程中根據(jù)設(shè)置的安全策略控制指令對(duì)外部資源的訪問(wèn)。

  Java的執(zhí)行方式不是編譯執(zhí)行而是解釋執(zhí)行,不同平臺(tái)上面相同的源代碼編譯成符合Java規(guī)范的相同的二進(jìn)制字節(jié)碼,然后再交給支持各自平臺(tái)的虛擬機(jī)去解釋執(zhí)行,"先編譯,后解釋,再執(zhí)行"三步走的方式使得Java實(shí)現(xiàn)了"一次編寫(xiě),到處運(yùn)行",如果Java應(yīng)用使用的是100%標(biāo)準(zhǔn)Java API并且沒(méi)有直接調(diào)用本地方法,那就可以不加修改地運(yùn)用在多種平臺(tái)上,這樣的平臺(tái)無(wú)關(guān)性使得在異構(gòu)的網(wǎng)絡(luò)環(huán)境或者嵌入式方面的應(yīng)用更方便和現(xiàn)實(shí)。Java的網(wǎng)絡(luò)移動(dòng)性帶來(lái)了一種全新的軟件模式,在分布式處理模式的基礎(chǔ)之上,可以將軟件和數(shù)據(jù)通過(guò)網(wǎng)絡(luò)傳送到客戶端去,這樣確保了客戶端有必備的軟件來(lái)瀏覽和操縱通過(guò)網(wǎng)絡(luò)傳輸?shù)臄?shù)據(jù),Java體系結(jié)構(gòu)支持把單一的執(zhí)行文件切割成小的二進(jìn)制字節(jié)碼文件Class文件,而這些文件可以按照應(yīng)用的需要?jiǎng)討B(tài)連接、動(dòng)態(tài)擴(kuò)展。Java體系結(jié)構(gòu)對(duì)安全性的支持主要是通過(guò)Java語(yǔ)言本身安全性、虛擬機(jī)的類加載器和安全管理器以及Java提供的安全API幾個(gè)方面來(lái)實(shí)現(xiàn):防止惡意程序的攻擊,程序不能破壞用戶計(jì)算機(jī)環(huán)境;防止入侵,程序不能獲取主機(jī)或所在內(nèi)網(wǎng)的保密信息;鑒別,驗(yàn)證程序提供者和使用者的身份;加密,對(duì)傳輸交換的數(shù)據(jù)進(jìn)行加密,或者給持久化的數(shù)據(jù)進(jìn)行加密;驗(yàn)證,對(duì)操作設(shè)置規(guī)則并且進(jìn)行驗(yàn)證。

  Java信息安全的必要性

  隨著互聯(lián)網(wǎng)應(yīng)用越來(lái)越廣泛,并且互聯(lián)網(wǎng)其本身獨(dú)特的資源共享性,因此能夠按照用戶需求及時(shí)準(zhǔn)確獲得信息和處理信息的應(yīng)用對(duì)用戶而言就相當(dāng)重要,這也是Java得以迅速發(fā)展和被廣泛接受的原因。但同時(shí)網(wǎng)絡(luò)也提供了一條攻擊接入計(jì)算機(jī)的潛在途徑,特別是當(dāng)用戶下載網(wǎng)絡(luò)軟件在本地運(yùn)行,這就要求Java能夠?qū)Σ《?木馬的問(wèn)題加以防范,對(duì)信息以及本地環(huán)境進(jìn)行保護(hù)。比如我們?yōu)g覽一個(gè)網(wǎng)頁(yè)的時(shí)候,網(wǎng)頁(yè)上的Applet可能會(huì)自動(dòng)下載并且運(yùn)行,而這個(gè)Applet完全有可能來(lái)自不可靠的地方,又或者我們使用通過(guò)JINI服務(wù)查找到的網(wǎng)絡(luò)上不可靠的服務(wù)對(duì)象來(lái)獲得服務(wù),如果沒(méi)有Java體系結(jié)構(gòu)提供的安全機(jī)制,這就很有可能引入了一個(gè)懷有敵意的程序造成信息丟失、資料泄密、相信偽造數(shù)據(jù)和修改本地計(jì)算機(jī)安全設(shè)置等等后果,帶來(lái)未知的嚴(yán)重后果。

  Java語(yǔ)言本身安全性

  Java語(yǔ)言的設(shè)計(jì)者們是在C++的基礎(chǔ)上設(shè)計(jì)出來(lái)Java的,因此與C++相比它的語(yǔ)法更加簡(jiǎn)單清晰,結(jié)構(gòu)、單元、運(yùn)算符重載、虛擬基礎(chǔ)類等在Java中都沒(méi)有采用,并且取消了多重繼承而采用實(shí)現(xiàn)多個(gè)接口的方式。這樣能降低開(kāi)發(fā)人員犯錯(cuò)誤的幾率,幫助他們寫(xiě)出更安全的代碼。

  Java中去除了C++語(yǔ)言中的令人費(fèi)解、容易出錯(cuò)的"指針",用列表、堆、哈希表等結(jié)構(gòu)來(lái)代替,避免了任何不安全的結(jié)構(gòu)。Java也沒(méi)有索引核查的數(shù)組訪問(wèn),因?yàn)檫@往往會(huì)導(dǎo)致不定的、不可預(yù)測(cè)的程序操作,它所有的數(shù)組訪問(wèn)都必須先檢查是否越界。Java要求所有的變量在初始化以前不能使用,對(duì)于基本數(shù)據(jù)類型變量都會(huì)自動(dòng)地賦給某個(gè)初始值,避免了未初始化變量獲取內(nèi)存信息。所有這些都使得程序不能訪問(wèn)任意的內(nèi)存地址,對(duì)于內(nèi)存中的實(shí)體信息只能通過(guò)有權(quán)限的對(duì)象進(jìn)行訪問(wèn),而不會(huì)出現(xiàn)象C++那樣把類型指針強(qiáng)制轉(zhuǎn)換成內(nèi)存的指針,然后通過(guò)內(nèi)存查找的方法找到私有的變量。

  Java分配內(nèi)存對(duì)于開(kāi)發(fā)人員來(lái)說(shuō)是透明的,開(kāi)發(fā)人員使用new方法新建對(duì)象,這時(shí)候虛擬機(jī)就會(huì)從堆內(nèi)存中找到合適的內(nèi)存空間,開(kāi)發(fā)人員不需要也不能夠進(jìn)行干預(yù)。而對(duì)于內(nèi)存的回收,Java避免了開(kāi)發(fā)人員明確干預(yù)對(duì)象的回收,比如C的free或C++的delete命令,避免了開(kāi)發(fā)人員無(wú)意間對(duì)內(nèi)存的破壞。Java采用虛擬機(jī)的"垃圾回收"機(jī)制來(lái)實(shí)現(xiàn)的內(nèi)存自動(dòng)管理,釋放不再被使用的內(nèi)存資源,內(nèi)存回收器就像一臺(tái)垃圾收集車,但是和我們?cè)诖蠼稚峡吹降氖占嚕瑑H僅收集大家放在垃圾桶里面的垃圾不同的是,它還要到你家里去幫你找出那些東西是不要用的垃圾,然后把這些東西拿走,最后還要整理家里的空間,騰出最大的空間讓你放新東西。Java的內(nèi)存回收器目的就是找到不再引用的對(duì)象,釋放內(nèi)存空間,并且需要整理內(nèi)存的碎片空間,盡量避免出現(xiàn)"內(nèi)存不足"的情況。

  對(duì)于在網(wǎng)絡(luò)中交換的序列化對(duì)象很容易在重建對(duì)象的時(shí)候訪問(wèn)到對(duì)象的私有信息,這時(shí)候Java提供了兩種辦法來(lái)保護(hù)信息,一種就是采用給變量加上transient關(guān)鍵字的方法,這樣對(duì)象序列化的時(shí)候就不會(huì)讀寫(xiě)該變量,另一種就是在實(shí)現(xiàn)Externalizable接口而不是Serizlizable接口,這樣對(duì)象就只能通過(guò)writeExternal和readExternal方法來(lái)保存和重建,其他方法無(wú)法進(jìn)行了。

  以上這些都是Java語(yǔ)言本身對(duì)信息安全提供的基礎(chǔ)。

   類加載器

  雖然名字叫類加載器,但是實(shí)際上Java虛擬機(jī)中的類加載器不光要負(fù)責(zé)加載而且要負(fù)責(zé)連接和初始化應(yīng)用程序需要用到的Java類型。加載就是把二進(jìn)制形式的字節(jié)碼讀入虛擬機(jī)中,而連接就是給這個(gè)已經(jīng)讀入的類型分配類變量?jī)?nèi)存以及把類型中用到常量池中的符號(hào)轉(zhuǎn)換為直接引用,最后的初始化過(guò)程就是賦給類型變量合適的初始值。

  類加載器為加載的類提供了不同的命名空間,統(tǒng)一源代碼生成的字節(jié)碼被加載到同一個(gè)命名空間中,相同命名空間不能加載類名相同的類,同一個(gè)命名空間內(nèi)的類可以直接進(jìn)行交互,而不同的命名空間的類是不能交互的,除非顯式地提供了交互機(jī)制,通過(guò)命名空間和類成員訪問(wèn)權(quán)限的設(shè)置保護(hù)了被信任的類邊界。

  類加載器分成了啟動(dòng)類加載器、標(biāo)準(zhǔn)擴(kuò)展類加載器、路徑類加載器和網(wǎng)絡(luò)類加載器四種。啟動(dòng)類加載器從本地系統(tǒng)中加載原始的Java API類,用來(lái)啟動(dòng)Java虛擬機(jī),而其他三種加載器是在運(yùn)行時(shí)加載用戶定義的類,標(biāo)準(zhǔn)擴(kuò)展類加載器加載的是不同虛擬機(jī)提供商擴(kuò)展的標(biāo)準(zhǔn)Java類,而在classpath中的類由路徑類加載器來(lái)加載,網(wǎng)絡(luò)類加載器加載通過(guò)網(wǎng)絡(luò)下載得到的類文件,每一種加載器在加載類的時(shí)候都會(huì)建立一個(gè)加載器實(shí)例。類加載器采用雙親委派鏈模式(這個(gè)模式很類似GOF在《設(shè)計(jì)模式》一書(shū)中提到的責(zé)任鏈模式)除了啟動(dòng)類加載器以外,每個(gè)類加載器都有自己的"雙親"。一個(gè)類可以通過(guò)有三種方法定義自己的雙親:第一種通過(guò)引用,比如A類中引用了B類(即A和B有關(guān)聯(lián)關(guān)系),那么B類的加載器就會(huì)作為A類的加載器的"雙親",早于A類加載;第二種使用loadClass方法來(lái)自定義"雙親",這時(shí)被load的類的"雙親"即本身這個(gè)類加載器;第三種在沒(méi)有采用前兩種的情況下使用的默認(rèn)方式,默認(rèn)把啟動(dòng)類加載器作為"雙親"。

  在加載過(guò)程中,當(dāng)發(fā)出加載請(qǐng)求的時(shí)候,加載器首先詢問(wèn)它的"雙親"――路徑類加載器――來(lái)查找并加載這個(gè)類,而這個(gè)加載器也向它的"雙親"請(qǐng)求加載,一層一層請(qǐng)求上去,直到啟動(dòng)加載器獲得請(qǐng)求,來(lái)查找并加載這個(gè)類,如果這個(gè)類沒(méi)有被加載并且查找不到,返回結(jié)果給它的子加載器,由子加載器加載,直到請(qǐng)求返回給原來(lái)的加載器,這時(shí)還沒(méi)有加載成功的話,由網(wǎng)絡(luò)類加載器試圖從網(wǎng)絡(luò)中尋找并下載,如果還不成功將拋出NoClassDefFoundError異常。

  這個(gè)過(guò)程保證了啟動(dòng)類加載器可以搶在標(biāo)準(zhǔn)擴(kuò)展類加載器之前加載類,而標(biāo)準(zhǔn)擴(kuò)展類加載器又可以搶在路徑類加載器之前加載類,最后才由網(wǎng)絡(luò)類加載器加載。比如應(yīng)用被試圖加載一個(gè)帶有惡意代碼的java.lang.String類,因?yàn)樗緛?lái)是Java API的一部分,它們加載到的命名空間可以得到被信任類的特殊訪問(wèn)權(quán)限,但是由于啟動(dòng)類加載器是最早被加載的,所以java.lang.String只會(huì)被啟動(dòng)類從Java原始的API中加載,而帶有惡意代碼的java.lang.String類不會(huì)被加載進(jìn)來(lái),這樣有效的保護(hù)了被信任的類邊界。

  類加載器中還包括了一個(gè)類型檢查的功能模塊,它負(fù)責(zé)保證程序的健壯性,它在類型的生命周期中要進(jìn)行四次檢查。第一次檢查是在加載的時(shí)候,主要檢查二進(jìn)制字節(jié)碼的結(jié)構(gòu),首先格式要滿足Java語(yǔ)言定義的規(guī)范,然后要保證將要加載的類字節(jié)碼是一組合法的Java指令。第二次檢查是在連接的時(shí)候,主要是類型數(shù)據(jù)的語(yǔ)義檢查,保證字節(jié)碼在編譯時(shí)候遵守了規(guī)范,比如對(duì)final類不會(huì)派生出子類,也不會(huì)重載final的方法;每個(gè)類只有一個(gè)超類;沒(méi)有把基本數(shù)據(jù)類型強(qiáng)制轉(zhuǎn)換成其他數(shù)據(jù)類型。第三次檢查也是在連接的時(shí)候,關(guān)注于指令的結(jié)構(gòu),保證指令的操作數(shù)類型和值正確,操作數(shù)堆棧不會(huì)出現(xiàn)上溢出或者下溢出。最后一次檢查在動(dòng)態(tài)連接的時(shí)候,主要檢查類型中的符號(hào)引用被解析時(shí)是否正確。以上的問(wèn)題都會(huì)產(chǎn)生惡意的行為所以必須在運(yùn)行前進(jìn)行檢查,而一部分檢查工作會(huì)在虛擬機(jī)運(yùn)行字節(jié)碼的時(shí)候檢查,比如數(shù)組越界,對(duì)象類型的轉(zhuǎn)換等等,一旦檢查發(fā)現(xiàn)了問(wèn)題就會(huì)拋出異常,使得程序不被執(zhí)行。

  類加載器避免了出現(xiàn)某些懷有敵意的人編寫(xiě)自己的Java類,而這些類方法中含有跳轉(zhuǎn)到方法之外的指令,導(dǎo)致虛擬機(jī)的崩潰和保密信息被獲取的可能,保證了程序的健壯性,也不會(huì)出現(xiàn)替代原有Java API類的惡意代碼被運(yùn)行的情況,并且類加載器防止了惡意代碼去干涉善意的代碼,守護(hù)了被信任的API類庫(kù)邊界,確保了代碼可以進(jìn)行的操作。

   安全管理器

  安全管理器為Java虛擬機(jī)的環(huán)境建立了一個(gè)起到保護(hù)作用的"沙箱",這個(gè)"沙箱"為程序提供了一個(gè)限制了應(yīng)用的操作運(yùn)行環(huán)境,保護(hù)了虛擬機(jī)外部的資源不會(huì)被虛擬機(jī)內(nèi)部的惡意代碼破壞。安全管理器的安全策略可以靈活的建立細(xì)粒度的訪問(wèn)控制策略,將不同的資源訪問(wèn)權(quán)限授予不同的代碼單元,這也是Java體系結(jié)構(gòu)安全模型的最大特點(diǎn)和優(yōu)勢(shì)之一。

  首先在賦予權(quán)限前我們要明確代碼單元的來(lái)源,簽名擔(dān)?梢允褂脩舸_認(rèn)文件的來(lái)源,并且這些文件在本地虛擬機(jī)加載前沒(méi)有被修改,只有保證了源代碼來(lái)源的可靠性,才能分配相應(yīng)的操作權(quán)限。對(duì)class文件或者jar文件的簽名可以用jdk中的jarsigner這個(gè)工具。它首先對(duì)根據(jù)文件內(nèi)容進(jìn)行單向散列計(jì)算,產(chǎn)生一個(gè)散列值,然后把這個(gè)散列加到文件后面作為文件的一部分傳遞給用戶,用戶收到文件后重新生成一次散列值,然后跟文件后部的散列值進(jìn)行比較,如果這兩個(gè)散列值相同說(shuō)明文件內(nèi)容沒(méi)有被改動(dòng),雖然不同的文件內(nèi)容可能生成相同的散列值,但是一般Java采用的是124位散列,這個(gè)長(zhǎng)度想要從一個(gè)不同的輸入產(chǎn)生一個(gè)已知散列值的計(jì)算是不可行的。僅僅通過(guò)散列值是沒(méi)有辦法保證代碼的來(lái)源的,因?yàn)閼延袗阂獾娜送耆梢园颜麄(gè)文件和散列值都替換掉,為了防止這種事情發(fā)生,必須在發(fā)送前用私鑰對(duì)散列值進(jìn)行加密,為什么不對(duì)整個(gè)文件進(jìn)行加密呢,因?yàn)閖arsigner默認(rèn)采用的是DES算法,加密本身也是一個(gè)費(fèi)時(shí)的過(guò)程,我們的目的只是為了保證文件的來(lái)源而不是文件本身的保密性,所以只需要對(duì)散列值進(jìn)行加密,用戶收到文件以后用文件提供者的公鑰進(jìn)行解密來(lái)驗(yàn)證散列值沒(méi)有被替換。

  明確了代碼來(lái)源,并且保證沒(méi)有被修改以后,就可以給它分配操作權(quán)限。安全策略是一個(gè)java.sercurity.Policy的實(shí)現(xiàn)類,Policy中主要包含了代碼來(lái)源和相應(yīng)的權(quán)限的對(duì)應(yīng)關(guān)系信息,安全管理器的check方法將根據(jù)Policy對(duì)象判斷給導(dǎo)入的代碼賦予什么樣的操作權(quán)限。代碼來(lái)源是由java.security.CodeSource表示的,這個(gè)對(duì)象中包含了一組Certificate對(duì)象,說(shuō)明了為這個(gè)代碼文件擔(dān)保的簽名。而權(quán)限是用java.sercurity.Permission的子類實(shí)例來(lái)表示的,每一個(gè)Permission有三個(gè)屬性:類型、名稱和可進(jìn)行的操作,類型說(shuō)明了權(quán)限控制的資源類型,比如FilePermission說(shuō)明了是對(duì)文件操作的權(quán)限,名稱說(shuō)明了這個(gè)權(quán)限控制的對(duì)象,比如FilePermission的名稱為"/mydoc/order.txt",說(shuō)明了對(duì)文件order.txt的操作權(quán)限,可進(jìn)行的操作屬性說(shuō)明了這個(gè)權(quán)限可以進(jìn)行的操作,比如"read"說(shuō)明這個(gè)FilePermission可以對(duì)order.txt進(jìn)行讀操作。

  開(kāi)發(fā)人員可以通過(guò)編寫(xiě)代碼繼承SecurityManager類建立自己的安全管理器來(lái)設(shè)置安全策略,更方便和常用的方法是通過(guò)設(shè)置策略文件來(lái)實(shí)現(xiàn)。這是一個(gè)策略文件的例子:

  //從mykeys文件中獲得簽名的公鑰
  keystore "mykeys"
  //由father簽名的代碼賦予讀order.txt文件的權(quán)限
  grant signedBy "father"{
  permission java.io.FilePermission "order.txt","read";
  }
  //來(lái)自{Java_Home}/security/ex/目錄下面的所有jar文件和class文件有讀寫(xiě)order.txt文件的權(quán)限
  grant codeBase "file:${Java_Home}/security/ex/*"{
  permission java.io.FilePermission "order.txt","read,write";
  }
  //來(lái)自{Java_Home}/security/ex/目錄下面的帶有wife簽名的所有jar文件和class文件有接受、連接和監(jiān)聽(tīng)8080端口的權(quán)限
  grant signedBy "wife" codeBase "file:${Java_Home}/security/ex/*"{
  permission java.io.SocketPermission "*:8080","accept,connect,listen";
  }
  //所有代碼都有讀寫(xiě)appversion.properties文件的權(quán)限
  grant {
  permission java.io.FilePermission "appversion.properties","read,write";
  }

  如果一個(gè)應(yīng)用程序沒(méi)有指定啟動(dòng)安全管理器進(jìn)行干預(yù),它的所有操作不會(huì)受到管理器的限制,指定啟動(dòng)安全管理器有兩種方式,一種是在運(yùn)行應(yīng)用程序的時(shí)候指定,一種是在代碼中指定。

  java -Djava.serciruty.manager myapplication

  這里指定了啟動(dòng)默認(rèn)安全管理器,這時(shí)候?qū)⒏鶕?jù)Java默認(rèn)的全局策略文件來(lái)設(shè)置安全策略,這個(gè)文件是

  /JAVA_HOME/lib/security/java.policy。
  java -Djava.serciruty.manager -Djava.serciruty.policy= myapplication

  這里啟動(dòng)安全管理器,除了默認(rèn)的全局策略文件外,也會(huì)按照Djava.serciruty.policy參數(shù)指定的策略文件來(lái)設(shè)置安全策略,文件指定可以用URL也可以直接用文件名稱。

  如果是在代碼中指定,程序通過(guò)setSecurityManager方法設(shè)置一個(gè)java.lang.SecurityManager的實(shí)例時(shí)候,這時(shí)候安全管理器就會(huì)開(kāi)始控制應(yīng)用程度的操作了。這時(shí)當(dāng)類加載器加載類到虛擬機(jī)的時(shí)候,安全管理器根據(jù)代碼來(lái)源和簽名找到相應(yīng)的權(quán)限,然后建立這個(gè)類的保護(hù)域ProtectionDomain,保護(hù)域定義了這個(gè)類所有的權(quán)限。當(dāng)應(yīng)用程序用到這個(gè)類并要進(jìn)行任何可能的不安全操作時(shí),都會(huì)向安全管理器請(qǐng)求操作許可,安全管理器中有一系列的check方法來(lái)檢查操作是否可行,比如checkRead方法會(huì)檢查是否能夠讀取某個(gè)文件,checkWrite方法檢查是否能夠?qū)懭肽硞(gè)文件,管理器根據(jù)操作請(qǐng)求類型調(diào)用相關(guān)的check方法,check方法根據(jù)類的保護(hù)域判斷操作是否可行,如果操作沒(méi)有權(quán)限的話將拋出一個(gè)異常,操作收到這個(gè)異常后將不能執(zhí)行,如果操作可行的話,check方法就順利返回,操作繼續(xù)執(zhí)行。

  以上簽名驗(yàn)證、定義安全策略以及安全管理器檢查操作權(quán)限一系列過(guò)程,有效的保護(hù)了被Java應(yīng)用使用的外部資源的安全性。要注意的是而由啟動(dòng)類加載器加載的核心API類是不受這個(gè)安全管理器的權(quán)限控制,這也是為什么要用類加載器防止核心API被惡意代碼替換的原因。

   Java體系結(jié)構(gòu)提供的安全API

  Java體系結(jié)構(gòu)提供了三類主要的安全API:Java 認(rèn)證和授權(quán)服務(wù)(Java Authentication and Authorization Service,JAAS)、Java 安全套接字?jǐn)U展(Java Secure Socket Extension,JSSE)和 Java 加密擴(kuò)展(Java Cryptography Extension,JCE)。前面已經(jīng)提到了安全管理器中用到的JAAS,這一節(jié)我們提到的是API主要指Java提供的對(duì)信息進(jìn)行加密的Java加密擴(kuò)展包JCE和Java安全套接字?jǐn)U展包JSSE, 這些API提供了加密算法可以按照我們的需要,實(shí)現(xiàn)對(duì)任意數(shù)據(jù)的加密和解密。

  Java加密擴(kuò)展包JCE提供的是基于密鑰的加密,它通過(guò)javax.crypto.Cipher類來(lái)實(shí)現(xiàn)數(shù)據(jù)加密合解密,加密解密的對(duì)象可以使程序中的數(shù)組對(duì)象,也可以是通過(guò)Java流接口讀出或者寫(xiě)入的數(shù)據(jù)。使用Cipher類加密可以選擇多種加密算法、加密模式和填補(bǔ)機(jī)制。加密算法JCE中提供了DES、多重DES、PBEWithMD5AndDES、RSA和Blowfish等等。DES是很多機(jī)構(gòu)組織采用的數(shù)據(jù)加密標(biāo)準(zhǔn);而多重DES使用多個(gè)DES密碼進(jìn)行多長(zhǎng)DES加密,加大了攻擊的難度但是也增加了加密解密過(guò)程說(shuō)花的時(shí)間;PBEWithMD5AndDES前面提到過(guò),主要是計(jì)算散列,然后對(duì)散列進(jìn)行DES加密,來(lái)實(shí)現(xiàn)簽名認(rèn)證;RSA算法是1978年公布的一種分組加密算法,也是現(xiàn)在應(yīng)用得最廣泛的公鑰密鑰算法;Blowfish是由Bruce Schneier公布的一種加密算法,沒(méi)有申請(qǐng)專利,并且公布了實(shí)現(xiàn)的代碼,它適合不需要經(jīng)常更換密鑰的情況。

  選擇加密模式是為了對(duì)加密數(shù)據(jù)做進(jìn)一步調(diào)整,從而增加解密難度,模式還可以將分組明文作為流明文進(jìn)行處理,減少每次處理的數(shù)據(jù)量,JCE中提供了電子密碼本模式ECB、密碼封裝鏈接模式CBC、密碼反饋模式CFB和輸出反饋模式OFB。電子密碼本模式ECB是最簡(jiǎn)單的一種模式,只是對(duì)明文每8個(gè)字節(jié)進(jìn)行分組,并且一次完成整個(gè)明文分組的加密,它適合對(duì)二進(jìn)制數(shù)據(jù)流進(jìn)行加密;密碼封裝鏈接模式CBC,把一個(gè)8字節(jié)的分組作為輸入數(shù)據(jù)對(duì)另一組加密結(jié)果進(jìn)行修正,這樣可以把明文中包含的數(shù)據(jù)類型進(jìn)行隱藏,這種模式可以對(duì)文本數(shù)據(jù)進(jìn)行加密;密碼反饋模式CFB,類似于CBC模式只是實(shí)現(xiàn)稍有不同,不同的是CBC模式需要明文分組來(lái)進(jìn)行修正,而CFB需要的數(shù)據(jù)量小一些,并且長(zhǎng)度可以進(jìn)行調(diào)整;輸出反饋模式OFB,適合那種加密數(shù)據(jù)在傳輸過(guò)程中有可能產(chǎn)生變化的情況,產(chǎn)生變化出錯(cuò)只會(huì)對(duì)這一位產(chǎn)生影響而不會(huì)影響整個(gè)分組。JCE可以選擇兩種填補(bǔ)機(jī)制PCKS5Padding和NoPadding,前者將對(duì)明文進(jìn)行分組時(shí)候,如果字節(jié)數(shù)不夠8的倍數(shù)就進(jìn)行填充,保證數(shù)據(jù)的長(zhǎng)度為一個(gè)完整的分組,而后者不對(duì)數(shù)據(jù)進(jìn)行填充,當(dāng)明文進(jìn)行分組時(shí)候,字節(jié)數(shù)不夠8的倍數(shù)會(huì)拋出一個(gè)異常。

  Java安全套接字?jǐn)U展包JSSE提供的是基于套接字之間傳輸?shù)臄?shù)據(jù)進(jìn)行加密,它與JCE最大的不同就是數(shù)據(jù)的加密過(guò)程和傳輸過(guò)程是不分離的,如果說(shuō)JAAS讓我們可以識(shí)別應(yīng)用程序提供者并限制他們只能訪問(wèn)授權(quán)使用的那部分系統(tǒng),那么JSSE保證了我們應(yīng)用程序傳輸?shù)臄?shù)據(jù)安全性。JSSE實(shí)現(xiàn)了SSL(安全套接字層)的加密,SSL作為HTTPS協(xié)議的基礎(chǔ),提供了在TCP套接字上對(duì)數(shù)據(jù)進(jìn)行加密的方法,也是基于WEB應(yīng)用最常用的一種加密方式。使用JSSE API首先我們需要建立SSL環(huán)境,SSL服務(wù)器端建立密鑰庫(kù)存放服務(wù)器私鑰和驗(yàn)證身份的證書(shū),而SSL客戶端建立信任庫(kù)驗(yàn)證信任的證書(shū),密鑰庫(kù)和信任庫(kù)都是通過(guò)JDK中keytool這個(gè)工具來(lái)進(jìn)行管理;其次,我們需要從一個(gè) JSSE 套接字工廠而不是直接從 java.net.Socket 類獲得套接字,客戶端代碼從 SSLSocketFactory 獲取套接字,而服務(wù)器端代碼從 SSLServerSocketFactory 獲取套接字;通過(guò)從這些工廠獲取套接字,我們就可以利用 JSSE 提供程序提供的框架,而不是像 java.net 包允許我們所作的那樣,簡(jiǎn)單地創(chuàng)建標(biāo)準(zhǔn)的、不安全的套接字。使用 JSSE,我們可以定義運(yùn)行任意應(yīng)用程序協(xié)議--包括 HTTP、TCP/IP、FTP,甚至 Telnet--的客戶機(jī)與服務(wù)器之間的安全套接字連接。

  總結(jié):

  信息的安全性是計(jì)算機(jī)領(lǐng)域必須重視和解決的問(wèn)題,Java體系結(jié)構(gòu)對(duì)信息安全的提供靈活而健壯框架,只要我們使用得當(dāng)就能夠很好的保證信息安全性,降低我們的代價(jià)和風(fēng)險(xiǎn),同時(shí)我們也要加強(qiáng)一些其他相關(guān)的安全工作,比如保護(hù)好我們的私鑰等等,這樣才能保證Java安全框架發(fā)揮最大的作用。Java安全框架還有一些不足的地方,比如應(yīng)用程序不斷分配內(nèi)存或者新建線程造成拒絕服務(wù)、將安全模型與系統(tǒng)用戶進(jìn)行映射等等,隨著信息技術(shù)的不斷發(fā)展,信息安全也會(huì)面臨越來(lái)越大的挑戰(zhàn),這些都需要Java安全框架更加完善和進(jìn)一步發(fā)展。