标簽(空格分隔): Java 安全
[toc]
Java的安全軟體特性,是通過安全軟體包的概念透出的。換句話說,安全領域常見的鑒别、加密、簽名等概念,在Java中的支援是通過安全軟體包來實作的。Java對于安全軟體包的定義其實是一組抽象接口。Sun作為Java的作者,提供了一組實作。而安全軟體包是由安全提供者、算法和引擎組成的。引擎可以了解為一組操作,算法定義了操作如何執行,而安全提供者則負責實作這兩個抽象概念。
比如說,消息摘要是一個引擎,它是程式員能執行的一個操作。消息摘要的思想與如何計算消息摘要沒有關系,所有的消息摘要具備同樣的特性,是以抽象出來的接口就是引擎。而實作消息摘要可以有MD5和SHA等算法,算法由具體類實作。而安全提供者就是二者的橋梁,用來管理引擎和算法。安全提供者的目的就是提供一個簡單的機制,進而可以友善的改變或替換算法及其實作。是以,通過安全提供者,程式員隻需要使用引擎的接口,而不需要關系具體哪個類實作了算法,算法由哪個安全提供者提供。
Java安全軟體包的體系結構可以總結為四個部分:
JVM提供引擎類,是Java核心API的一部分。
針對每一種引擎,都會有一組算法實作。Java提供了一組預設的算法實作(由Sun提供),第三方的機構可以提供其他實作。
算法類是由提供者來管理的,提供者知道如何将算法與實作的具體類對應起來。
安全類儲存提供者清單,可以通過安全類檢視有哪些提供者,以及它們提供的算法支援有哪些。
安全提供者體系的一個流程如下:
以MessageDigest的getInstance()方法為例,發現其實是調用Security.getImpl()方法實作的,而内部又是通過
這樣的語句來做的。而這個GetInstance會傳回一個Instance對象,其類聲明如下:
可見就是一個Provider和Object(具體算法)的封裝。
JVM在啟動時,會去$JREHOME/lib/security/java.security中注冊提供者。以我個人電腦中的檔案為例:
JVM啟動時會将這些provider注冊進去,其實就是Security
初始化時會讀這個檔案。開發自定義的安全提供者,需要将類放到系統類路徑下。其實看看Provider類的代碼,就知道Provider本質上是一個Properties檔案,裡面的kv存儲着引擎名和具體算法類的實作。
可以通過下面的程式示例檢視具體的提供者引擎和算法:
其輸出如下,(截取部分)
值得一提的是引擎類的結構設計。如上所說,引擎類除了給業務開發人員提供接口,還有一個任務就是要為第三方提供者使用。引擎為提供者提供了一個接口——SPI(security provider interface)。
還是以MessageDigest為例(這是消息摘要引擎)。MessageDigest繼承了MessageDigestSpi。MessageDigestSpi抽象類定義了消息摘要引擎要做的事情。MessageDigest内部持有一個Delegate委托類,MessageDigest的核心方法就是getInstance()擷取類的執行個體,實作見下:
通過Security.getImpl()反射擷取到對應的provider和算法實作類,并通過類型判斷和else委托邏輯保證傳回一個MessageDigest執行個體。
再具體一點,以Sun security提供的MD5算法實作為例。雖然MD5并沒有直接實作MessageDigestSpi,但MD5的父類DigestBase繼承了MessageDigestSpi。是以實際上還是滿足這個架構的設計。DigestBase做了消息摘要通用的實作,留了三個abstract接口:
這幾個代碼在MD5中具體實作:(截取部分)
最後補充一個類圖說明下類的結構: