從早期所謂的 Java 沙箱到 JDK 1.4 引入的健壯的、全功能的安全體系結構,安全性一直是 Java 平台的基本組件。從那時到現在,Java 語言的設計者收到了來自團體的大量關於安全的 Java 應用程序(或者企業環境)可以做什麼和不做什麼的意見,他們自己也添加了若干技巧。
可以說隨著 J2EE Web 應用程序安全體系結構的引入,我們不斷從近 10 年的反復試驗有所收獲,事實也表明了這一點。J2EE 安全框架由三個 API 組成:Java 認證和授權服務(JAAS)、Java 安全套接字擴展(JSSE)和 Java 加密擴展(Java Cryptography Extension,JCE)。雖然 JCE 是一個有意思和重要的 API,但是它與我們所關注的安全 Web 應用程序開發的“三大項”――認證、授權和傳輸――並不特別相關。所以在本月的專欄中我們將集中講述 JAAS 和 JSSE。
JAAS 和 JSSE 概述
JAAS 提供了一種靈活的、說明性的機制,用於對用戶進行認證並驗證他們訪問安全資源的能力。JSSE 定義了通過安全套接字層(SSL)進行安全 Web 通信的一種全 Java 的機制。通過結合這兩種技術,可以使我們的應用程序:
驗證用戶就是他或者她所宣稱的那個人(認證)。
保證允許他或者她訪問所要求的資源(授權)。
通過安全網絡連接進行完整的信息交換(傳輸)。
現在,我們來看每一個基礎的功能組件。
用 JAAS 進行認證
JAAS 建立在一種稱為可插入的認證模塊(Pluggable Authentication Module,PAM)的安全體系結構之上。PAM 的體系結構是 模塊化的,這意味著它設計為可以通過交換模塊,支持從一個安全協議組件無縫地轉換到另一個協議組件。這個框架中定義良好的接口使得無需改變或者干擾任何現有的登錄服務就可以加入多種認證技術和授權機制。PAM 體系結構可以集成范圍廣泛的認證技術,包括 RSA、DCE、Kerberos 以及 S/Key,因而 JAAS 也可以集成這些技術。此外,這個框架與基於智能卡的認證系統和 LDAP 認證兼容。
就像許多 Java 2 平台技術一樣,JAAS API 定義了應用程序代碼與將要執行業務邏輯的物理實現之間干淨的抽象。這個抽象層不用重新編譯現有的應用程序代碼就可以作為登錄模塊的運行時替代。特別是,應用程序寫到 LoginContext API,而認證技術提供程序則寫到 LoginModule 接口。在運行時, LoginContext 將讀取配置文件以確定應使用哪一個(一些)登錄模塊對訪問特定應用程序的用戶進行認證。
JAAS 所使用的認證方案以兩種非常重要的實體為基礎:principal 和 subject。實際被認證的人或者服務稱為 subject。principal是一個惟一的實體,比如個人或者組的名字、帳號、社會安全號或者類似的惟一標識。為了惟一標識一個 subject(這是認證的關鍵部分),一個或者多個 principal 必須與這個 subject 相關聯。最後,一個 subject 可能擁有安全相關的屬性,稱為 憑證(credential)。憑證可以是從簡單的密碼到復雜的加密密鑰的任何東西。
應用程序通過實例化一個 LoginContext 對象開始認證過程。LoginContext 查詢一個配置文件以確定進行認證所使用的一種(或者多種)認證技術以及相應的一個(或者多個) LoginModule 。一個非常簡單的 LoginModule 可能會提示輸入用戶名和密碼並對它們進行驗證。高級一點的可能會使用現有的操作系統登錄身份進行身份驗證。理論上,甚至可以將一個 JAAS LoginModule 構建成與指紋識別器或者虹膜掃描儀交互。
用 JAAS 進行授權
認證只是 Java 安全框架任務的一半。當用戶的身份被確認後,必須對他或者她的訪問權限進行檢查。只有確認了適當的權限後,用戶才可以訪問安全的系統或者資源。
換一種說法,驗證了用戶或者服務的身份後,就創建一個 Subject 對象來表示經過驗證的實體。然後 JAAS 將這個對象傳遞給任何為保護對敏感系統或資源的訪問而建立的授權組件。
要確定授權,可以向 Java 2 Security Manager 提供 Subject 及其 Principal s,以及 Subject 要執行的特權操作(讀/寫到文件系統、數據庫訪問,等等)。Security Manager 會咨詢與 Principal s 和權限相關聯的策略文件。如果一個 Subject 的 Principal s 具有執行指定操作的權限,那麼就對這個 Subject 授權並允許操作,否則就會拒絕這項操作並拋出一個 SecurityException 。
用 JSSE 進行安全傳輸
有了 JAAS ,我們就可以識別訪問系統的用戶並限制他們只能訪問授權使用的那部分系統。雖然 JAAS 是邁向安全 Web 應用程序堅實的第一步,但是如果沒有安全傳輸,那麼應用程序安全性仍然是不完整的。
這裡,我們仍然是以明文形式――即 HTTP、TCP/IP、FTP等――傳遞安全信息(包括認證信息)。所以我們需要保證數據在傳輸時不會被未授權的人訪問。我們還需要保證數據在到達之前,沒有在傳輸過程中修改過,不管這種修改是有意的還是無意的。我們可以利用安全套接字層(SSL)和傳輸層安全性(Transport Layer Security,TLS)協議實現這兩種功能。
SSL 和 TLS 不是特定於 Java 的協議,它們是為維護通過套接字的數據的完整性和私密性而設計的網絡層協議。Java 安全套接字擴展(JSSE)利用 SSL/TLS 可以進行安全的 Internet 通信,它提供了一個具有完整功能的應用程序框架――一個 Java 版本的 SSL 和 TLS 協議,這些功能包括數據加密、服務器認證、消息完整性,等等。使用 JSSE,我們可以定義運行任意應用程序協議――包括 HTTP、TCP/IP、FTP,甚至 Telnet――的客戶機與服務器之間的安全套接字連接。從數據加密的角度看,JSSE 結合了許多與 JCE 中使用的同樣的概念和算法。不過更重要的是,在簡單流套接字 API 背後,它會在必要時自動使用它們。
要利用 JSSE API,我們只需要做簡單的幾件事。首先我們需要獲得 JSSE 提供程序(請參閱 參考資料)。其次,我們需要從一個 JSSE 套接字工廠而不是直接從 java.net.Socket 類獲得套接字。客戶端代碼從 SSLSocketFactory 獲取套接字,而服務器端代碼從 SSLServerSocketFactory 獲取套接字。通過從這些工廠獲取套接字,我們就可以利用 JSSE 提供程序提供的框架,而不是像 java.net 包允許我們所作的那樣,簡單地創建標准的、不安全的套接字。
有關 JSSE 的更多細節,請參閱 參考資料。
結束語
Java 平台以其巖石般堅固的安全性聞名。每一年 Java 安全性框架都會變得更靈活和更健壯,JAAS 和 JSSE 的加入表明這個傳統將會繼續發揚光大。
本月,我們快速回顧了保證 Java Web 應用程序安全的技術。JAAS 提供了對用戶進行認證和控制訪問資源的模塊化機制。JSSE 提供了 SSL 和 TSL 協議的 Java 實現以支持數據完整性和私密性。下個月,我們將探討 servlet 過濾器的全新世界。那時再見,祝您探索快樂!