Java核心技術卷二筆記9
第九章 安全
對Java而言,安全機制是一個不可分割的組成部分。Java提供以下三種確保安全的機制:
- 語言設計特性,如對陣列的邊界檢查。
- 訪問控制機制,如檔案訪問。
- 程式碼簽名,程式碼的使用者可以知道誰建立了程式碼以及是否被修改。
類載入器
類載入過程
每個Java程式至少擁有三個類載入器
- 引導類載入器,用於載入系統類,沒有ClassLoader物件
- 擴充套件類載入器。從jre/lib/ext目錄載入標準的擴充套件
- 系統類載入器,載入應用類
類載入器的層次結構
類載入器有一種父子關係,除了引導類載入器之外,每個類載入器都有一個父類載入器。載入時會先載入父類,只有當父類載入器載入失敗後才會載入給定類。
每一個執行緒都一個對類載入器的引用,稱為上下文載入器。主執行緒的上下文類載入器是系統類載入器。當新執行緒被建立時,它的上下文類載入器就是建立該執行緒的上下文類載入器。因此所有執行緒的預設上下文載入器是系統類載入器。
類載入器作為名稱空間
同一個虛擬機器中可以有類名和包名完全相同的兩個類。
自定義類載入器
自定義類載入器只需要將其繼承ClassLoader類,覆蓋findClass方法。ClassLoader類本身的超類的loadClass方法將類的載入操作委託給其父類載入器進行,只有該類及其父類都未載入該類時才呼叫findClass方法。
實現findClass方法,首先要為來自本地檔案及其他各個來源的類載入其位元組碼,其次要呼叫ClassLoader超類的defieClass方法,向虛擬機器提供位元組碼。
位元組碼校驗
當類載入器將自己嗎傳遞給虛擬機器時,位元組碼要先接受校驗器的校驗。校驗器負責檢查那些指令無法執行的有明顯破壞性的操作。除了系統類外的所有類都要被校驗,校驗器有以下校驗內容。
- 變數在使用前需初始化。
- 方法呼叫和物件引用型別之間要匹配。
- 訪問私有資料和方法的規則沒有被違反。
- 對本地變數的訪問都落在執行時堆疊內。
- 執行時堆疊沒有溢位。
安全管理器和訪問許可權
許可權檢查
安全管理器是一個負責控制u具體操作是否允許執行的類。
Java平臺安全性
從Java1.2之後,Java平臺的安全策略建立了程式碼來源和訪問許可權集之間的對映關係。
程式碼來源由一個程式碼位置和證書集組成,許可權是指由安全管理器負責檢查的任何屬性。
每個類都有一個保護域,它是用於封裝類的程式碼來源和許可權集合的物件。
安全策略檔案
策略管理器要讀取對應的策略檔案,這些檔案包含了將程式碼來源對映為許可權的指令。
Windows驅動器名前面的斜槓是可有可無的。
使用者認證
登入時要對登入的主體Subject進行認證,該主體可以有多個特徵principal。特徵描述了主體的某些屬性,比如使用者名稱、組ID、角色等。特徵管制著各個許可權。
數字簽名
訊息摘要
訊息摘要是資料塊的資料指紋。如SHA1可將任意長度資料塊壓縮為160位的序列。它具有兩個基本屬性。
- 如果資料改變了,訊息摘要也將改變。
- 擁有給定訊息的偽造者無法建立與原訊息具有相同摘要的假訊息。
MessageDigest類是用於建立封裝了指紋演算法的物件的工廠以及作為所有訊息摘要演算法的超類,它的靜態方法getInstance返回了繼承MessageDigest類的某個類的物件,其中的update方法需要在整個對位元組的迴圈中反覆呼叫。如果位元組存放在陣列中則可以省去迴圈,一次性完成整個陣列的更新。隨後呼叫的digest方法會議位元組陣列的形式返回訊息摘要。
訊息簽名
訊息傳送者對摘要進行私鑰加密形成簽名,訊息接收者對簽名使用公鑰解密,如果解密成功則說明訊息確實來自於該傳送者。
認證問題
通過一個受信任的中間人對傳送者的公共金鑰進行私鑰加密,接收方再對該加密後的公鑰使用中間人的公鑰進行解密,確保傳送方的公鑰的可靠性。
加密
對稱密碼
Cipher類是所有加密演算法的超類。通過getInstance方法獲取一個密碼物件,再對其設定模式和金鑰進行初始化。
非對稱密碼
非對稱密碼的關鍵在於使用接收者的公鑰將傳送者的對稱金鑰進行加密,該加密後的對稱金鑰只能被接收者用自己的私鑰解密。只有獲取解密後的傳送者的對稱金鑰,才能將加密後的明文解密。