安全公用 API
Liberty 中的安全公用 API 提供一個延伸安全基礎架構的方法。
Liberty 包含一些公用 API,可供您用來實作安全函數。Liberty 中的安全公用 API 是 WebSphere® Application Server traditional 安全公用 API 的子集。主要類別是 WSSecurityHelper、WSSubject 和 RegistryHelper。這些類別包含 WebSphere Application Server traditional 版本所提供之方法的子集。另外,還有一個新類別 WebSecurityHelper。
下列幾節說明這些主要類別。 另外,還有其他類別,例如 UserRegistry、WSCredential 及其他異常狀況類別。
Liberty 所支援的所有安全公用 API 都在 Java™ API 文件中。每一個 Liberty API 的 Java API 文件都是以個別的 .zip 檔來提供(其位於 ${wlp.install.dir}/dev 目錄的其中一個 javadoc 子目錄中)。
- WSSecurityHelper
- 這個類別只包含 isServerSecurityEnabled() 和 isGlobalSecurityEnabled() 方法。 此外,如果啟用了 appSecurity-2.0 或 zosSecurity-1.0,這些呼叫會傳回 true。否則,這些方法會傳回 false。這些方法是為了相容性,而從 WebSphere Application Server traditional WSSecurityHelper 類別保持至今。
- 註:
- 在 Liberty 中沒有任何 Cell,因此,在 Liberty 中,廣域安全和伺服器安全沒有區別。因此,這兩個方法會傳回相同的值。
- Liberty 不支援 revokeSSOCookies(javax.servlet.http.HttpServletRequest req,javax.servlet.http.HttpServletResponse res) 方法。相反地,您可以使用 Servlet 3.0 登出功能。
- getLTPACookieFromSSOToken() 方法已重新命名為新的公用 API 類別:WebSecurityHelper。
- WSSubject
- 這個類別提供用來查詢及設定安全執行緒環境定義的公用程式方法。Liberty 支援 WebSphere Application Server traditional
WSSubject 中的所有方法。註: 支援「Java 2 安全」,但是依預設,不會在 Liberty 中啟用。因此依預設,不會在 WSSubject 中執行 Java 2 安全檢查。
- RegistryHelper
- 這個類別可供存取 UserRegistry 物件及授信網域範圍資訊。 在 Liberty 中,它包含下列 WebSphere Application Server traditional 方法子集:
- public static UserRegistry getUserRegistry(String realmName) throws WSSecurityException
- public static List<String> getInboundTrustedRealms(String realmName) throws WSSecurityException
- public static boolean isRealmInboundTrusted(String inboundRealm, String localRealm)
- WebSecurityHelper
- 這個類別包含從 WSSecurityHelper 移來而重新命名的 getLTPACookieFromSSOToken() 方法:
- public static Cookie getSSOCookieFromSSOToken() throws Exception
- PasswordUtil
- 此類別提供編碼和解碼方法,來保護機密性資訊。如果要啟用此項以作為 API,請在 server.xml 檔中配置 passwordUtilities-1.0 特性。註: 此類別亦存在於完整設定檔中。不過,Liberty 設定檔可新增更多功能,以提供其他的方法。
安全公用 API 程式碼範例
下列範例示範如何利用 Liberty 中的安全公用 API,來執行程式化登入及處理主體。
- 範例 1:建立一個 Subject,利用它來進行授權
- 這個範例示範如何利用 WSSecurityHelper、WSSubject 和 UserRegistry 執行程式化登入來建立 Java Subject,然後執行一個動作,並將這個 Subject 用於任何必要的授權。
註: 在執行進一步的安全處理之前,下列程式碼利用 WSSecurityHelper 來檢查是否已啟用安全。基於 Liberty 的模組化本質,這項檢查得到廣泛的運用:如果未啟用安全,就不會載入安全執行時期。WSSecurityHelper 一律會載入,即使未啟用安全也一樣。
import java.rmi.RemoteException; import java.security.PrivilegedAction; import javax.security.auth.Subject; import javax.security.auth.callback.CallbackHandler; import javax.security.auth.login.LoginContext; import javax.security.auth.login.LoginException; import com.ibm.websphere.security.CustomRegistryException; import com.ibm.websphere.security.UserRegistry; import com.ibm.websphere.security.WSSecurityException; import com.ibm.websphere.security.WSSecurityHelper; import com.ibm.websphere.security.auth.WSSubject; import com.ibm.websphere.security.auth.callback.WSCallbackHandlerImpl; import com.ibm.wsspi.security.registry.RegistryHelper; public class myServlet { ... if (WSSecurityHelper.isServerSecurityEnabled()) { UserRegistry ur = null; try { ur = RegistryHelper.getUserRegistry(null); } catch (WSSecurityException e1) { // 記錄一些診斷資訊 return; } String userid = "user1"; String password = "user1password"; try { if (ur.isValidUser(userid)) { // 建立一個 Subject,利用 // 使用者 ID 和密碼來進行鑑別 CallbackHandler wscbh = new WSCallbackHandlerImpl(userid, password); LoginContext ctx; ctx = new LoginContext("WSLogin", wscbh); ctx.login(); Subject subject = ctx.getSubject(); // 利用 Subject,針對任何必要的授權, // 來執行動作。 WSSubject.doAs(subject, action); } } catch (CustomRegistryException e) { // 記錄一些診斷資訊 return; } catch (RemoteException e) { // 記錄一些診斷資訊 return; } catch (LoginException e) { // 記錄一些診斷資訊 return; } } ... private final PrivilegedAction action = new PrivilegedAction() { @Override public Object run() { // 在這裡執行一些有用的動作 return null; } }; }
- 範例 2:建立一個 Subject,將它設為執行緒上的現行 Subject
- 下列範例示範如何利用 WSSecurityHelper 和 WSSubject 執行程式化登入來建立 Java Subject,使這個 Subject 成為執行緒的現行 Subject,最終還原原始安全執行緒環境定義。
註: 在執行進一步的安全處理之前,下列程式碼利用 WSSecurityHelper 來檢查是否已啟用安全。
import javax.security.auth.Subject; import javax.security.auth.callback.CallbackHandler; import javax.security.auth.login.LoginContext; import javax.security.auth.login.LoginException; import com.ibm.websphere.security.WSSecurityException; import com.ibm.websphere.security.WSSecurityHelper; import com.ibm.websphere.security.auth.WSSubject; import com.ibm.websphere.security.auth.callback.WSCallbackHandlerImpl; ... if (WSSecurityHelper.isServerSecurityEnabled()) { CallbackHandler wscbh = new WSCallbackHandlerImpl("user1", "user1password"); LoginContext ctx; try { // 建立一個 Subject,利用 // 使用者 ID 和密碼來進行鑑別 ctx = new LoginContext("WSLogin", wscbh); ctx.login(); Subject mySubject = ctx.getSubject(); Subject oldSubject = null; try { // 儲存指向執行緒現行 Subject 的參照 oldSubject = WSSubject.getRunAsSubject(); // 將 mySubject 設為執行緒的現行 Subject callbackHandler.handle(callbacks); // 在這裡執行一些有用的動作。任何必要的授權 // 都會利用 mySubject 來執行 } catch (WSSecurityException e) { // 記錄一些診斷資訊 return; } finally { // 將原始 Subject 放回執行緒環境定義中 if (oldSubject != null) { try { callbackHandler.handle(callbacks); } catch (WSSecurityException e) { // 記錄一些診斷資訊 } } } } catch (LoginException e) { // 記錄一些診斷資訊 return; } }
- 範例 3:取得執行緒上現行 Subject 的資訊
- 下列範例示範如何利用 WSSecurityHelper、WSSubject 和 WSCredential 來取得執行緒上現行 Subject 的相關資訊。
註: 在執行進一步的安全處理之前,下列程式碼利用 WSSecurityHelper 來檢查是否已啟用安全。
import java.util.ArrayList; import java.util.Iterator; import java.util.Set; import javax.security.auth.Subject; import javax.security.auth.login.CredentialExpiredException; import com.ibm.websphere.security.WSSecurityException; import com.ibm.websphere.security.WSSecurityHelper; import com.ibm.websphere.security.auth.CredentialDestroyedException; import com.ibm.websphere.security.auth.WSSubject; import com.ibm.websphere.security.cred.WSCredential; ... if (WSSecurityHelper.isServerSecurityEnabled()) { // 取得呼叫端的主體 Subject callerSubject; try { callerSubject = WSSubject.getCallerSubject(); } catch (WSSecurityException e) { // 記錄一些診斷資訊 return; } WSCredential wsCred = null; Set<WSCredential> wsCredentials = callbackHandler.handle(callbacks); Iterator<WSCredential> wsCredentialsIterator = wsCredentials.iterator(); if (wsCredentialsIterator.hasNext()) { wsCred = wsCredentialsIterator.next(); try { // 將群組印出 ArrayList<String> groups = wsCred.getGroupIds(); for (String group : groups) { System.out.println("Group name: " + group); } } catch (CredentialExpiredException e) { // 記錄一些診斷資訊 return; } catch (CredentialDestroyedException e) { // 記錄一些診斷資訊 return; } } } }