本文檔介紹了如何借助一個“數據庫”來配置 Tomcat ,從而實現容器管理安全性。所要連接的這種數據庫含有用戶名、密碼以及用戶角色。你只需知道的是,如果使用的 Web 應用含有一個或多個 元素, 元素定義了用戶驗證的必需細節信息。如果你不打算使用這些功能,則可以忽略這篇文檔。
關于容器管理安全性的基礎知識,可參考 Servlet Specification (Version 2.4) 中的第 12 節內容。
Realm(安全域)其實就是一個存儲用戶名和密碼的“數據庫”再加上一個枚舉列表。“數據庫”中的用戶名和密碼是用來驗證 Web 應用(或 Web 應用集合)用戶合法性的,而每一合法用戶所對應的角色存儲在枚舉列表中。可以把這些角色看成是類似 UNIX 系統中的 group(分組),因為只有能夠擁有特定角色的用戶才能訪問特定的 Web 應用資源(而不是通過對用戶名列表進行枚舉適配)。特定用戶的用戶名下可以配置多個角色。
雖然 Servlet 規范描述了一個可移植機制,使應用可以在 web.xml 部署描述符中聲明它們的安全需求,但卻沒有提供一種可移植 API 來定義出 Servlet 容器與相應用戶及角色信息的接口。然而,在很多情況下,非常適于將 Servlet 容器與一些已有的驗證數據庫或者生產環境中已存在的機制“連接”起來。因此,Tomcat 定義了一個 Java 接口(org.apache.catalina.Realm),通過“插入”組件來建立連接。提供了 6 種標準插件,支持與各種驗證信息源的連接:
另外,還可以編寫自定義 Realm 實現,將其整合到 Tomcat 中,只需這樣做:
在詳細介紹標準 Realm 實現之前,簡要了解 Realm 的配置方式是很關鍵的一步。大體來說,就是需要在conf/server.xml 配置文件中添加一個 XML 元素,如下所示:
<Realm className="... class name for this implementation"
???????... other attributes for?this?implementation .../> ?
可以嵌入以下任何一種 Container 元素中。Realm 元素的位置至關重要,它會對 Realm 的“范圍”(比如說哪個 Web 應用能夠共享同一驗證信息)有直接的影響。
對于每種標準 Realm 實現來說,用戶的密碼默認都是以明文方式保存的。在很多情況下,這種方式都非常糟糕,即使是一般的用戶也能收集到足夠的驗證信息,從而以其他用戶的信息成功登錄。為了避免這種情況的發生,標準 Realm 實現支持一種對用戶密碼進行摘要式處理的機制,它能以無法輕易破解的形式對存儲的密碼進行加密處理,同時保證Realm 實現仍能使用這種加密后的密碼進行驗證。
在標準的 Realm 驗證時,會將存儲的密碼與用戶所提供的密碼進行比對,這時,我們可以通過指定 元素中的 digest 屬性來選擇摘要式密碼。該屬性值必須是一種java.security.MessageDigest 類所支持的摘要式算法(SHA、MD2、或 MD5)。當你選擇該屬性值時,存儲在 Realm 中的密碼內容必須是明文格式,隨后它將被你所指定的算法進行摘要式加密。
在調用 Realm 的 authenticate() 方法后,用戶所提供的明文密碼同樣也會利用上述你所指定的加密算法進行加密,加密結果與 Realm 的返回值相比較。如果兩者相等,則表明原始密碼的明文形式更用戶所提供的密碼完全等同,因此該用戶身份驗證成功。
可以采用以下兩種比較便利的方法來計算明文密碼的摘要值:
如果應用需要動態計算摘要式密碼,調用 org.apache.catalina.realm.RealmBase 類的靜態 Digest() 方法,傳入明文密碼和摘要式算法名稱及字符編碼方案。該方法返回摘要式密碼。
如果使用 DIGEST 驗證的摘要式密碼,用來生成摘要密碼的明文密碼則將有所不同,而且必須使用一次不加鹽的 MD5 算法。對應到上面的范例,那就是必須把 {cleartext-password} 替換成 {username}:{realm}:{cleartext-password}。再比如說,在一個開發環境中,可能采用這種形式:testUser:Authentication required:testPassword。{realm} 的值取自 Web 應用 的 元素。如果沒有在 web.xml 中指定,則使用默認的Authentication required。
若要使用非平臺默認編碼的用戶名和(或)密碼,則命令如下:
CATALINA_HOME/bin/digest.[bat|sh] -a {algorithm} -e {encoding} {input}
但需要注意的是,一定要確保輸入正確地傳入摘要。摘要返回 {input}:{digest}。如果輸入在返回時出現損壞,摘要則將無效。
摘要的輸出格式為 {salt}${iterations}${digest}。如果鹽的長度為 0,迭代次數為 1,則輸出將簡化為 {digest}。
CATALINA_HOME/bin/digest.[bat|sh] 的完整格式如下:
CATALINA_HOME/bin/digest.[bat|sh] [-a ] [-e ]
????????[-i ] [-s ] [-k ]
????????[-h ] ??
Tomcat 自帶的范例應用中包含一個受到安全限制保護的區域,使用表單式登錄方式。為了訪問它,在你的瀏覽器地址欄中輸入 http://localhost:8080/examples/jsp/security/protected/,并使用 UserDatabaseRealm 默認的用戶名和密碼進行登錄。
如果你希望使用 Manager 應用在一個運行的 Tomcat 安裝上來部署或取消部署 Web 應用,那么必須在一個選定的 Realm 實現上,將 manager-gui 角色添加到至少一個用戶名上。這是因為 Manager 自身使用一個安全限制,要想在該應用的 HTML 界面中訪問請求 URI,就必須要有 manager-gui 角色。
出于安全性考慮,默認情況下,Realm 中的用戶名(比如使用 conf/tomcat-users.xml)沒有被分配 manager-gui 角色。因此,用戶起初無法使用這個功能,除非 Tomcat 管理員特意將這一角色分配給他們。
Realm 的容器(Context、Host 及 Engine)所對應的日志配置文件將記錄 Realm 所記錄下的調試和異常信息。