JAAS之Authentication
注:主要參考SUN的JAAS tutorial
Introduction(介紹)
使用JAAS有2個目的:
* 認證
for authentication of users, to reliably and securely determine who is currently executing Java code, regardless of whether the code is running as an application, an applet, a bean, or a servlet; and
* 授權
for authorization of users to ensure they have the access control rights (permissions) required to do the actions performed.
JAAS是一個可插拔的認證模塊,不管使用何種認證技術,認證程序使用保持獨立,也就是說新增或修改認證技術應用程序不用修改。應用認證是通過實例化一個LoginContext來實現(xiàn)的,并通過一個配置文件來決定使用哪種認證技術或者那些LoginModule去執(zhí)行驗證操作,典型的LoginModules是通過驗證用戶名和密碼,也有可能是通過聲音或者指紋來進行驗證。
一旦用戶或者服務通過認證,接著JAAS授權組件基于JAVA2訪問控制模型(Java 2 access control model)保護敏感的資源。不同的是JDK1.3或更早的版本的訪問控制是基于code的位置和code簽名。JDK1.4是基于執(zhí)行代碼CodeSource和運行這個代碼的用戶或者服務(用Subject表示),驗證成功以后這個Subject被修改,設置相關的Principals 和credentials
JAAS Authentication(JAAS認證)
JAAS認證的操作通俗一點講,無非有三點:
1. 如何獲取驗證數(shù)據(jù)(這里的sample用用戶名和密碼)
2. 進行驗證
3. 保存驗證后的信息。
我們看一下client端調(diào)用的主要代碼如下:
LoginContext lc = new LoginContext("Sample", new MyCallbackHandler(username,password));
lc.login()
lc.getSubject();;
這三 行代碼里就包含了上面講的三點,其中:
[a]“sample”是指屬性文件中的信息,指出使用哪個登錄的LoginModule和其它一些參數(shù)。比如:
Sample {
com.sample.SampleLoginModule required debug=true;
};
[b] MyCallbackHandler就是如何獲取驗證數(shù)據(jù),其中傳遞了Username和password參數(shù)
public class MyCallbackHandler implements CallbackHandler {
private String username;
private String password;
public MyCallbackHandler(String username, String password) {
super();
this.username = username;
this. password = password;
}
public void handle(Callback callbacks[]) throws IOException,
UnsupportedCallbackException {
for (int i = 0; i < callbacks.length; i++) {
if (callbacks[i] instanceof NameCallback) {
((NameCallback) callbacks[i]).setName(username);
} else if (callbacks[i] instanceof PasswordCallback) {
((PasswordCallback) callbacks[i]).setPassword(password);
} else {
throw new UnsupportedCallbackException(callbacks[i]);
}
}
}
}
[c] 驗證登錄調(diào)用的是com.sample.SampleLoginModule的login方法
public boolean login() throws LoginException {
//


















.
Callback[] callbacks = new Callback[2];
callbacks[0] = new NameCallback("user name: ");
callbacks[1] = new PasswordCallback("password: ", false);
callbackHandler.handle(callbacks);
String username = ((NameCallback) callbacks[0]).getName();
String password = ((PasswordCallback) callbacks[1]).getPassword();
//利用回調(diào)獲取用戶名和密碼后,怎么進行驗證都可以.
//




















[d] 最后保存信息調(diào)用的是commit方法,修改Subject
public boolean commit() throws LoginException {
if (succeeded == false) {
return false;
} else {
// add a Principal (authenticated identity)
// to the Subject
// assume the user we authenticated is the SamplePrincipal
userPrincipal = new SamplePrincipal(username);
if (!subject.getPrincipals().contains(userPrincipal))
subject.getPrincipals().add(userPrincipal);
//…………………………………………….
運行代碼時,需要加入?yún)?shù)-Djava.security.auth.login.config==sample_jaas.config sample.SampleAzn制定confg的位置
如果需要完整的代碼請參考sun網(wǎng)站的 jaas指南,詳情見文章后的參考資源。
如果這些代碼運行在Security Manager之下則涉及到JAAS授權,下篇文章再關注。
參考資源:
http://java.sun.com/j2se/1.5.0/docs/guide/security/jaas/tutorials/GeneralAcnOnly.html
附錄:
LoginModule描述由身份驗證技術提供程序實現(xiàn)的接口。LoginModule 插入到應用程序中以提供特定類型的身份驗證。
當應用程序寫入 LoginContext API 時,身份驗證技術提供程序將實現(xiàn) LoginModule接口。Configuration指定將與特定登錄應用程序一起使用的 LoginModule(s)。因此可以將不同的 LoginModule 插入到應用程序中,而無需修改應用程序本身。
LoginContext負責讀取 Configuration和實例化適當?shù)?nbsp;LoginModule。每個 LoginModule都是使用 Subject、CallbackHandler、共享的 LoginModule狀態(tài)和特定于 LoginModule 的選項來實例化的。 Subject表示當前正進行身份驗證的 Subject,如果身份驗證成功,則使用相關的 Credential 更新它。LoginModule 使用CallbackHandler與用戶進行通信。例如,CallbackHandler可以用于提示要求用戶名和密碼。注意, CallbackHandler可以為 null。確實需要一個 CallbackHandler來對 Subject進行身份驗證的 LoginModule 可以拋出 LoginException。LoginModule 可以有選擇地使用共享狀態(tài)來共享它們之間的信息或數(shù)據(jù)。
特定于 LoginModule 的選項表示由管理員或用戶在 Configuration中為此 LoginModule配置的選項。這些選項由 LoginModule自身定義,并在其中控制其行為。例如,LoginModule可以定義支持調(diào)試/測試功能的選項。這些選項是使用鍵-值語法定義的,例如 debug=true。LoginModule以 Map形式存儲這些選項,因此可以使用鍵來檢索這些值。注意,對 LoginModule選擇定義的選項個數(shù)是沒有限制的。
調(diào)用應用程序將身份驗證過程視為單個操作。但是,LoginModule中的身份驗證過程分兩個不同的階段進行。在第一個階段,LoginModule 的 login方法由 LoginContext 的 login方法調(diào)用。LoginModule的 login方法執(zhí)行實際的身份驗證(例如,提示并驗證密碼),并將身份驗證狀態(tài)作為私有狀態(tài)信息保存。一旦完成上述操作,LoginModule 的 login將返回 true(如果成功)或 false(如果應該忽略它),或拋出 LoginException來指示失敗。在失敗的情況下,LoginModule不必再嘗試進行身份驗證或者引入延遲。由應用程序完成這類任務。如果應用程序試圖重新嘗試身份驗證,將會再次調(diào)用 LoginModule 的 login方法。
在第二個階段,如果 LoginContext 的整個身份驗證成功(相關的 REQUIRED、REQUISITE、SUFFICIENT 和 OPTIONAL LoginModule 成功),則調(diào)用 LoginModule的 commit方法。LoginModule的 commit方法檢查其私有保存狀態(tài),以查看自己的身份驗證是否成功。如果整個 LoginContext身份驗證成功,并且 LoginModule 自己的身份驗證也獲得成功,則 commit方法會將相關的 Principal(已進行身份驗證的身份)和 Credential(身份驗證數(shù)據(jù),如加密密鑰)與位于 LoginModule中的 Subject聯(lián)系在一起。
如果 LoginContext 的整個身份驗證失敗(相關的 REQUIRED、REQUISITE、SUFFICIENT 和 OPTIONAL LoginModule 沒有成功),則調(diào)用每個 LoginModule的 abort方法。在這種情況下,LoginModule移除/銷毀原先保存的任何狀態(tài)。
注銷 Subject只涉及一個階段。LoginContext調(diào)用 LoginModule 的 logout方法。然后 LoginModule的 logout方法執(zhí)行注銷過程,例如從 Subject中移除 Principal 或 Credential,或者記錄會話信息。
LoginModule實現(xiàn)必須有一個無參數(shù)的構造方法。這允許加載 LoginModule的類對其進行實例化
。