Java Authentication and Authorization Service (JAAS) 採用可插拔認證模組 (PAM) 風格架構,通過配置文件動態綁定實現應用代碼與具體認證機制(LDAP、數據庫、Kerberos、NT、Unix 等)解耦。
| 類/介面 | 角色 |
|---|---|
LoginContext | 應用層入口,讀取配置、加載 LoginModule、驅動認證流程 |
LoginModule | SPI 接口,具體認證邏輯實現(如 JndiLoginModule、Krb5LoginModule) |
CallbackHandler | 收集認證憑證(用戶名/密碼、證書等),隔離交互細節 |
Subject | 認證主體,攜帶 Principals(身份)與 Credentials(憑證) |
Principal | 身份標識(用戶名、郵箱、證書 DN 等) |
LoginContext("appName"),指定配置文件中的應用名LoginContext 讀取配置,實例化對應的 LoginModule 數組login() 觸發兩階段認證:
login() 收集/驗證憑證,返回 true/falsecommit() 填充 Subject;否則調用 abort() 清理Subject 執行特權操作:Subject.doAs(subject, action)MyApp {
com.example.RdbmsLoginModule required
driver="com.mysql.jdbc.Driver"
url="jdbc:mysql://localhost/authdb"
debug="true";
com.sun.security.auth.module.NTLoginModule sufficient;
};
Flag 含義:
required:必須成功,繼續執行後續 Modulerequisite:必須成功,失敗則立即終止認證sufficient:成功則整體成功(若無前置 required 失敗),失敗繼續optional:成功與否不影響整體結果public class RdbmsLoginModule implements LoginModule {
public void initialize(Subject subject, CallbackHandler handler,
Map sharedState, Map options) {
// 保存參數,讀取 options 中的 url、driver 等
}
public boolean login() throws LoginException {
// 1. 創建 NameCallback、PasswordCallback
// 2. callbackHandler.handle(callbacks) 獲取用戶輸入
// 3. JDBC 驗證用戶名/密碼
// 4. 設置 success 標誌
return true;
}
public boolean commit() {
if (success) {
subject.getPrincipals().add(new UserPrincipal(username));
subject.getPrivateCredentials().add(password);
}
return success;
}
// abort() 清理,logout() 移除憑證
}
使用 ConsoleCallbackHandler 從標準輸入讀取:
LoginContext lc = new LoginContext("MyApp", new ConsoleCallbackHandler());
lc.login();
無法使用控制台交互,需實現被動式 CallbackHandler,從 Request 參數獲取憑證:
public class PassiveCallbackHandler implements CallbackHandler {
private final String username, password;
public PassiveCallbackHandler(String u, String p) { ... }
public void handle(Callback[] callbacks) {
for (Callback cb : callbacks) {
if (cb instanceof NameCallback) ((NameCallback)cb).setName(username);
else if (cb instanceof PasswordCallback) ((PasswordCallback)cb).setPassword(password.toCharArray());
}
}
}
容器配置(以 Resin 為例):
<system-property
java.security.auth.login.config="/resin/conf/jaas.config"/>
sharedState Map 在 Module 間傳遞數據Policy、Permission 實現基於角色的訪問控制 (RBAC)