java jaas_JAAS 参考指南
術語中英對照
縮寫
全拼
中文解釋
JAAS
Java Authentication and Authorization Service
Java身份驗證和授權服務
PAM
Pluggable Authentication Module
可插拔身份驗證模塊
概覽
JAAS 代表Java身份驗證和授權服務,它被用于兩個目的:
用戶認證,可靠且安全地確定當前是誰在執行Java代碼
用戶授權,確保他們擁有執行操作所需的訪問控制權限。
JAAS實現了標準可插拔身份驗證模塊(PAM)框架的Java版本
傳統的java提供了基于codesource-based 訪問控制(訪問控制基于代碼的來源和誰簽名了該代碼)。但是,它缺乏根據誰運行代碼來附加強制訪問控制的能力。JAAS提供了一個框架,通過這種支持來增強Java安全體系結構。
JAAS身份驗證是以可插入的方式執行的。這允許應用程序獨立于底層身份驗證技術,可以在應用程序下插入新的或更新的身份驗證技術,而不需要修改應用程序本身。應用程序通過實例化LoginContext對象來啟用身份驗證過程,而LoginContext對象又引用Configuration 或 LoginModule,用于執行身份驗證。典型的LoginModules可能會提示輸入和驗證用戶名和密碼
執行代碼的用戶或服務經過身份驗證后,JAAS授權組件將與核心Java SE訪問控制模型一起工作,以保護對敏感資源的訪問。訪問控制決策既基于執行代碼的CodeSource,也基于運行代碼的用戶或服務,后者由Subject對象表示,如果身份驗證成功,則使用相關Principals和credentials 的LoginModule更新Subject。
核心類和接口
與jaas相關的核心類和接口可以分為三類:Common, Authentication, and Authorization.
Common 類
公共類是由JAAS身份驗證和授權組件共享的類。關鍵的JAAS類是javax.security.auth.Subject,它表示單個實體(如人)的相關信息的分組。它包含實體的Principals、公共credentials和私有credentials
Subject
要授權訪問資源,應用程序首先需要對請求的源進行身份驗證。JAAS框架定義了表示請求源的術語subject。主體可以是任何實體,例如人或服務。一旦對主題進行了身份驗證,則使用javax.security.auth.Subject由關聯的標識或Principals填充。一個subject可能有多個principal。例如,一個人可能有一個name Principal(“John Doe”)和一個SSN Principal(“123-45-6789”)
subject還可以擁有與安全性相關的屬性,這些屬性稱為credentials憑據,敏感的credentials比如私鑰使用Set privCredentials表示,共享非敏感credentials比如公鑰使用Set pubCredentials表示。訪問和修改不同的憑據集需要不同的權限(如下所述):
subject是使用這些構造函數創建的:
public Subject();
public Subject(boolean readOnly, Set principals,
Set pubCredentials, Set privCredentials);
第一個構造函數創建了一個principal和credential為空(非空)的subject。第二個構造函數使用指定的principals和credentials創建subject。它還有一個布爾參數,可用于使subject為只讀。在只讀subject中,principals和credentials是不可變的。
應用程序編寫者不必實例化subject。如果應用程序實例化了一個LoginContext,而沒有將Subject傳遞給LoginContext構造函數,那么LoginContext實例化了一個新的空Subject
如果沒有在實例化Subject使其處于只讀狀態,則可以通過調用以下方法將其設置為只讀:
public boolean isReadOnly();
要獲取與subject相關的principals,有兩種方法:
public Set getPrincipals();
public Set getPrincipals(Class c);
第一個方法返回subject中的所有principals,而第二個方法只返回指定類c的實例或類c的子類的實例化的principals。如果subject沒有任何關聯的principals,則返回一個空集合。
獲取subject的公有憑證和私有憑證的方式和獲取主體的方式類似
public Set getPublicCredentials();
public Set getPublicCredentials(Class c);
public Set getPrivateCredentials();
public Set getPrivateCredentials(Class c);
要修改或操作subject的principals、pubCredentials或privCredentials,調用者使用java.util.Set中定義的方法。下面的示例演示了這一點:
Subject subject;
Principal principal;
Object credential;
. . .
// add a Principal and credential to the Subject
subject.getPrincipals().add(principal);
subject.getPublicCredentials().add(credential);
主題可以與AccessControlContext關聯,下面的方法返回與指定AccessControlContext關聯的subject,如果沒有與指定AccessControlContext關聯的subject,則返回null。
public static Subject getSubject(final AccessControlContext acc);
作為特定Subject執行操作的doAs方法
可以調用下列靜態方法來執行作為特定Subject的操作:
public static Object
doAs(final Subject subject,
final java.security.PrivilegedAction action);
public static Object
doAs(final Subject subject,
final java.security.PrivilegedExceptionAction action)
throws java.security.PrivilegedActionException;
這兩個方法首先將指定的Subject與當前線程的AccessControlContext關聯,然后執行操作。這實現了將動作作為Subject運行的效果。第一個方法可以拋出運行時異常,但正常執行時它必須從其action參數的run方法返回一個對象,第二個方法的行為類似,只是它可以從PrivilegedExceptionAction的 run方法中拋出一個已檢查的異常
Subject.doAs Example
假設名為“Bob”的人已經通過LoginContext(請參閱LoginContext)進行了身份驗證,因此,Subject 中填充了com.ibm.security.Principal類的Principal。這個Principal的名字叫BOB,還假設已經安裝了SecurityManager,并且訪問控制策略中存在以下內容:
// grant "BOB" permission to read the file "foo.txt"
grant Principal com.ibm.security.Principal "BOB" {
permission java.io.FilePermission "foo.txt", "read";
};
下面是示例應用程序代碼
class ExampleAction implements java.security.PrivilegedAction {
public Object run() {
java.io.File f = new java.io.File("foo.txt");
// the following call invokes a security check
if (f.exists()) {
System.out.println("File foo.txt exists");
}
return null;
}
}
public class Example1 {
public static void main(String[] args) {
// Authenticate the subject, "BOB".
// This process is described in the
// LoginContext class.
Subject bob;
// Set bob to the Subject created during the
// authentication process
// perform "ExampleAction" as "BOB"
Subject.doAs(bob, new ExampleAction());
}
}
在執行過程中,ExampleAction調用f.exists()時將遇到安全檢查。但是,由于ExampleAction作為“BOB”運行,并且策略(上面)將必要的文件權限授予“BOB”,因此ExampleAction將通過安全檢查。如果策略中的grant語句被更改(例如,添加不正確的CodeBase 或將主體更改為“MOE”),則會拋出SecurityException。
doAsPrivileged methods
public static Object doAsPrivileged(
final Subject subject,
final java.security.PrivilegedAction action,
final java.security.AccessControlContext acc);
public static Object doAsPrivileged(
final Subject subject,
final java.security.PrivilegedExceptionAction action,
final java.security.AccessControlContext acc)
throws java.security.PrivilegedActionException;
doAs與doAsPrivileged
doasprivilege方法的行為與doAs方法完全相同,只是它需要通過傳入一個AccessControlContext而不是將提供的subject與當前線程的AccessControlContext關聯。通過這種方式,可以通過與當前上下文不同的AccessControlContext來控制操作。
AccessControlContext包含自實例化AccessControlContext以來執行的所有代碼的信息,包括代碼位置和策略授予代碼的權限。為了使訪問控制檢查成功,策略必須為AccessControlContext引用的每個代碼項授予所需的權限。
如果提供給doasprivilege的AccessControlContext為null,則操作不受單獨的AccessControlContext的限制。比如在服務器環境中。服務器可以對多個傳入請求進行身份驗證,并為每個請求執行單獨的doAs操作。要啟動每個doAs操作,并且不受當前服務器AccessControlContext的限制,服務器可以調用doAsPrivileged并傳入null的AccessControlContext。
Principals
正如前面提到的,旦對主題進行了身份驗證,則使用javax.security.auth.Subject由關聯的標識或Principals填充。一個subject可能有多個principal。例如,一個人可能有一個name Principal(“John Doe”)和一個SSN Principal(“123-45-6789”)。主體必須實現java.security.Principal和java.io.Serializable的接口
Credentials
除了關聯的主體外,主題還可以擁有與安全性相關的屬性,這些屬性稱為憑據。憑據可能包含用于向新服務驗證主題的信息。這些憑證包括密碼、Kerberos票據和公鑰證書。憑據還可能包含僅使主體能夠執行某些活動的數據。例如,加密密鑰表示使主體能夠簽名或加密數據的憑據。公共憑證類和私有憑證類不是核心JAAS類庫的一部分。因此,任何類都可以表示憑證
:公共憑證類和私有憑證類不是核心JAAS類庫的一部分。然而,開發人員可以選擇讓他們的憑據類實現兩個與憑據相關的接口:Refreshable 和Destroyable。
Refreshable
javax.security.auth.Refreshable接口提供了憑據刷新自身的功能。例如,具有特定時間限制生命周期的憑據可以實現此接口,以允許調用者在其有效刷新刷新。該接口有兩種抽象方法:
boolean isCurrent();
此方法確定憑據是當前的還是有效的
void refresh() throws RefreshFailedException;
此方法更新或擴展憑據的有效性
Destroyable
javax.security.auth.Destroyable接口提供了銷毀憑據內內容的功能。該接口有兩個抽象方法
boolean isDestroyed();
確定憑據是否已被銷毀
void destroy() throws DestroyFailedException;
銷毀并清除與此憑據關聯的信息。對該憑證上的某些方法的后續調用將導致拋出IllegalStateException
Authentication 類和接口
認證是驗證subject身份的過程,必須以安全的方式執行;否則,犯罪者可能會冒充他人來訪問系統。身份驗證通常涉及到subject展示某種形式的證據來證明其身份。這些證據可能是只有受試者可能知道或擁有的信息(例如密碼或指紋),也可能是只有受試者能夠生成的信息(例如使用私鑰簽名的數據)。
要對subject(用戶或服務)進行身份驗證,需要執行以下步驟:
應用程序實例化LoginContext
LoginContext查詢一個Configuration,以加載為該應用程序配置的所有LoginModules 。
應用程序調用LoginContext的login 方法
login方法調用所有加載的LoginModules 。每個LoginModule都嘗試對subject進行身份驗證,成功后,LoginModules將相關principals和credentials與表示正在驗證的主題的Subject對象關聯。
LoginContext將身份驗證狀態返回給應用程序
如果身份驗證成功,應用程序將從LoginContext獲取主題。
LoginContext
javax.security.auth.login.LoginContext類提供了用于對subject進行身份驗證的基本方法,并提供了一種獨立于底層身份驗證技術開發應用程序的方法。LoginContext查詢配置,以確定為特定應用程序配置的身份驗證服務(或LoginModule)。因此,可以在應用程序下插入不同的LoginModules,而不需要對應用程序本身進行任何修改。
LoginContext提供了四個構造函數可供選擇:
public LoginContext(String name) throws LoginException;
public LoginContext(String name, Subject subject) throws LoginException;
public LoginContext(String name, CallbackHandler callbackHandler)
throws LoginException
public LoginContext(String name, Subject subject,
CallbackHandler callbackHandler) throws LoginException
所有構造函數都共享一個公共參數:name。LoginContext使用這個參數作為登錄配置的索引,以確定為實例化LoginContext的應用程序配置了哪些LoginModule
不接受Subject作為輸入參數的構造函數實例化一個新Subject。
實際身份驗證通過調用以下方法進行:
public void login() throws LoginException;
當調用login時,將調用所有配置的loginmodule來執行身份驗證。如果認證成功,可以使用以下方法檢索Subject(現在可以保存主體、公共憑證和私有憑證):
public Subject getSubject();
要注銷Subject并刪除其經過身份驗證的主體和憑據,提供以下方法:
public void logout() throws LoginException;
下面的代碼示例演示了驗證和注銷主題所需的調用:
// let the LoginContext instantiate a new Subject
LoginContext lc = new LoginContext("entryFoo");
try {
// authenticate the Subject
lc.login();
System.out.println("authentication successful");
// get the authenticated Subject
Subject subject = lc.getSubject();
...
// all finished -- logout
lc.logout();
} catch (LoginException le) {
System.err.println("authentication unsuccessful: " +
le.getMessage());
}
LoginModule
LoginModule接口使開發人員能夠實現可以在應用程序中插入的各種身份驗證技術。例如,一種類型的LoginModule可以執行基于用戶名/密碼的身份驗證形式。其他LoginModule可以與硬件設備(如智能卡或生物識別設備)來進行認證
CallbackHandler
在某些情況下,LoginModule必須與用戶通信才能獲得身份驗證信息javax.security.auth.callback.CallbackHandler就是用于此目的。應用程序實現CallbackHandler接口并將其傳遞給LoginContext,后者將其直接轉發給底層LoginModule
LoginModule使用CallbackHandler收集用戶的輸入(如密碼或智能卡密碼)或向用戶提供信息(如狀態信息),通過允許應用程序指定CallbackHandler,底層LoginModule可以實現不同的應用程序與用戶交互方式。例如,GUI應用程序的CallbackHandler實現可能會顯示一個窗口來請求用戶輸入。另一方面,非gui工具的CallbackHandler實現可能只是直接從命令行提示用戶輸入。
CallbackHandler是一個接口,有一個方法可以實現:
void handle(Callback[] callbacks)
throws java.io.IOException, UnsupportedCallbackException;
LoginModule向CallbackHandler 的handle方法傳遞一系列適當的回調函數,例如用戶名的NameCallback和密碼的PasswordCallback, CallbackHandler執行請求的用戶交互并在回調函數中設置適當的值。例如,要處理NameCallback, CallbackHandler可能會提示輸入名稱,然后獲取輸入name,并調用NameCallback的setName方法來存儲name。
Callback
javax.security.auth.callback包包含回調接口和幾個實現。LoginModules可以將一個回調數組直接傳遞給CallbackHandler的handle方法。
Authorization 類
總結
以上是生活随笔為你收集整理的java jaas_JAAS 参考指南的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: setState是异步还是同步?
- 下一篇: JAAS 汇总