JAAS Cheat Sheet / JAAS 欺骗表¶
Introduction - What is JAAS authentication / 简介 - 什么是 JAAS 认证¶
The process of verifying the identity of a user or another system is authentication.
验证用户或另一个系统身份的过程是认证。
JAAS, as an authentication framework manages the authenticated user's identity and credentials from login to logout.
The JAAS authentication lifecycle:
JAAS 认证生命周期:
- The application creates a
LoginContextusing the configured login name and a callback handler.
中文:应用程序使用配置的登录名和回调处理程序创建一个LoginContext。 - The
LoginContextreads the configuration and instantiates the configuredLoginModules.
中文:LoginContext读取配置并实例化配置的LoginModule。 - The
LoginContextcalls each module'sinitialize()with the sharedSubjectand other context.
中文:LoginContext使用共享的Subject和其他上下文调用每个模块的initialize()方法。 - The application calls
LoginContext.login(), which invokes the configured modules'login()methods according to their control flags.
中文:应用程序调用LoginContext.login(),该方法根据配置模块的控制标志调用各自的login()方法。 - If overall authentication succeeds, the
LoginContextinvokes the modules'commit()methods; otherwise, it invokes theirabort()methods.
中文:如果整体认证成功,LoginContext将调用模块的commit()方法;否则,将调用它们的abort()方法。
Configuration file / 配置文件¶
The JAAS configuration file contains a LoginModule stanza for each LoginModule available for logging on to the application.
JAAS 配置文件包含每个可用于登录应用程序的 LoginModule 的 LoginModule 配置段落。
A stanza from a JAAS configuration file:
JAAS 配置文件的一个段落:
Branches
{
USNavy.AppLoginModule required
debug=true
succeeded=true;
}
Note the placement of the semicolons, terminating both LoginModule entries and stanzas.
注意分号的位置,它们终止了 LoginModule 条目和段落。
The word required indicates the LoginContext's login() method must be successful when logging in the user. The LoginModule-specific values debug and succeeded are passed to the LoginModule.
单词 required 表示 LoginContext 的 login() 方法在登录用户时必须成功。LoginModule 特定的值 debug 和 succeeded 被传递给 LoginModule。
They are defined by the LoginModule and their usage is managed inside the LoginModule. Note, Options are Configured using key-value pairing such as debug="true" and the key and value should be separated by a = sign.
这些值由 LoginModule 定义,其使用在 LoginModule 内部管理。注意,选项通过键值对配置,例如 debug="true",键和值之间应以等号 = 分隔。
Main.java (The client) / Main.java(客户端)¶
- Execution syntax:
中文:执行语法:
Java –Djava.security.auth.login.config==packageName/packageName.config
packageName.Main Stanza1
Where:
packageName is the directory containing the config file.
packageName.config specifies the config file in the Java package, packageName.
packageName.Main specifies Main.java in the Java package, packageName.
Stanza1 is the name of the stanza Main() should read from the config file.
- When executed, the 1st command-line argument is the stanza from the config file. The Stanza names the
LoginModuleto be used. The 2nd argument is theCallbackHandler.
中文:执行时,第一个命令行参数是来自配置文件的段落。段落命名了要使用的LoginModule。第二个参数是CallbackHandler。 - Create a new
LoginContextwith the arguments passed toMain.java.
中文:使用传递给Main.java的参数创建一个新的LoginContext。loginContext = new LoginContext (args[0], new AppCallbackHandler());
- Call the LoginContext.Login Module:
中文:调用LoginContext.login()模块:loginContext.login();
LoginContext.login()returns without a value when authentication succeeds and throws aLoginExceptionwhen it fails.
中文:当认证成功时,LoginContext.login()无返回值,当失败时抛出LoginException异常。- Retrieve the authenticated
SubjectusingloginContext.getSubject()after successful login.
中文:使用loginContext.getSubject()在登录成功后检索已认证的Subject。
LoginModule.java¶
A LoginModule must have the following authentication methods:
一个 LoginModule 必须有以下认证方法:
initialize()login()commit()abort()logout()
initialize()¶
In Main(), after the LoginContext reads the correct stanza from the config file, the LoginContext instantiates the LoginModule specified in the stanza.
在 Main() 中,LoginContext 读取配置文件中的正确stanza后,LoginContext 实例化stanza中指定的 LoginModule。
initialize()methods signature:
中文:initialize()方法签名:public void initialize(Subject subject, CallbackHandler callbackHandler, Map<String, ?> sharedState, Map<String, ?> options)
- The arguments above should be saved as follows:
中文:上述参数应保存如下:this.subject = subject;this.callbackHandler = callbackHandler;this.sharedState = sharedState;this.options = options;
- What the
initialize()method does:
中文:initialize()方法的作用是:- Stores the supplied shared
Subject; successfulcommit()associates authenticated principals and credentials with that object.
中文:存储提供的共享Subject;成功的commit()将认证主体和凭证与该对象关联。 - Sets the
CallbackHandlerwhich interacts with the user to gather login information.
中文:设置与用户交互以收集登录信息的CallbackHandler。 - If a
LoginContextspecifies 2 or more LoginModules, which is legal, they can share information via asharedStatemap.
中文:如果LoginContext指定了 2 个或更多LoginModules,这是合法的,它们可以通过sharedState映射共享信息。 - Saves state information such as debug and succeeded in an options Map.
中文:在选项 Map 中保存状态信息,如调试和成功。
- Stores the supplied shared
login()¶
Captures user supplied login information. The code snippet below declares an array of two callback objects which, when passed to the callbackHandler.handle method in the callbackHandler.java program, will be loaded with a username and password provided interactively by the user:
捕获用户提供的登录信息。下面的代码片段声明了一个包含两个回调对象的数组,当将它们传递给 callbackHandler.handle 方法(在 callbackHandler.java 程序中)时,将加载用户通过交互提供的用户名和密码:
NameCallback nameCB = new NameCallback("Username");
PasswordCallback passwordCB = new PasswordCallback ("Password", false);
Callback[] callbacks = new Callback[] { nameCB, passwordCB };
callbackHandler.handle (callbacks);
- Authenticates the user
中文:验证用户身份 - Retrieves the user supplied information from the callback objects:
中文:从回调对象中检索用户提供的信息:String ID = nameCallback.getName ();char[] tempPW = passwordCallback.getPassword ();
- Compare
nameandtempPWto values stored in a repository such as LDAP.
中文:将name和tempPW与存储在如LDAP的存储库中的值进行比较。 - Set the value of the variable succeeded and return to
Main().
中文:设置succeeded变量的值并返回到Main()。
commit()¶
Once the users credentials are successfully verified during login(), the JAAS authentication framework associates the credentials, as needed, with the subject.
一旦在login()过程中成功验证了用户的凭据,JAAS认证框架将根据需要将凭据与主题关联。
A Subject separates credentials by their protection and sharing requirements:
【主题】通过保护和共享要求来分隔凭据(Subject)(https://docs.oracle.com/en/java/javase/11/docs/api/java.base/javax/security/auth/Subject.html):
- Public credentials are intended to be shared, such as public key certificates.
中文:公共凭据旨在共享,例如公钥证书。 - Private credentials require special protection, such as passwords and private cryptographic keys.
中文:私有凭据需要特殊保护,例如密码和私有加密密钥。
Principals (i.e. Identities the subject has other than their login name) such as employee number or membership ID in a user group are added to the subject.
主体(即除了登录名之外的主体身份,例如)如员工编号或用户组中的会员ID被添加到主体中。
Implement commit() using the authentication state saved by login(). Associate principals and credentials with the shared Subject only when this module's authentication succeeded; otherwise, clean up its saved state. Return true on success, false when the module is ignored, or throw LoginException on failure.
使用login()保存的认证状态实现commit()(https://docs.oracle.com/en/java/javase/11/docs/api/java.base/javax/security/auth/spi/LoginModule.html#commit())。只有在此模块的认证成功时,才将主体和凭据与共享的Subject关联;否则,清理其保存的状态。成功时返回true,当模块被忽略时返回false,或者在失败时抛出LoginException。
abort()¶
The abort() method is called when authentication doesn't succeed. Before the abort() method exits the LoginModule, care should be taken to reset state including the username and password input fields.
当认证不成功时调用abort()方法。在abort()方法退出LoginModule之前,应小心重置状态,包括用户名和密码输入字段。
logout()¶
The release of the users principals and credentials when LoginContext.logout is called:
当调用 LoginContext.logout 时释放用户主体和凭证:
public boolean logout() {
if (!subject.isReadOnly()) {
Set principals = subject.getPrincipals(UserGroupPrincipal.class);
subject.getPrincipals().removeAll(principals);
Set creds = subject.getPublicCredentials(UsernameCredential.class);
subject.getPublicCredentials().removeAll(creds);
return true;
} else {
return false;
}
}
CallbackHandler.java¶
The callbackHandler is in a source (.java) file separate from any single LoginModule so that it can service a multitude of LoginModules with differing callback objects:
将 callbackHandler 放置在源(.java)文件中,与任何单个 LoginModule 分离,以便它可以服务于具有不同回调对象的多个 LoginModule:
- Creates instance of the
CallbackHandlerclass and has only one method,handle().
中文:创建CallbackHandler类的实例,并只有一个方法,handle()。 - A
CallbackHandlerservicing a LoginModule requiring username & password to login:
中文:为需要用户名和密码登录的LoginModule提供服务的CallbackHandler:
public void handle(Callback[] callbacks) {
for (int i = 0; i < callbacks.length; i++) {
Callback callback = callbacks[i];
if (callback instanceof NameCallback) {
NameCallback nameCallBack = (NameCallback) callback;
nameCallBack.setName(username);
} else if (callback instanceof PasswordCallback) {
PasswordCallback passwordCallBack = (PasswordCallback) callback;
passwordCallBack.setPassword(password.toCharArray());
}
}
}
Related Articles / 相关文章¶
- JAAS in Action, Michael Coté, posted on September 27, 2009, URL as 5/14/2012.
- Pistoia Marco, Nagaratnam Nataraj, Koved Larry, Nadalin Anthony from book "Enterprise Java Security" - Addison-Wesley, 2004.
中文:Pistoia Marco, Nagaratnam Nataraj, Koved Larry, Nadalin Anthony 著,收录于《企业Java安全》一书 - Addison-Wesley,2004年链接。
Disclosure / 披露¶
All of the code in the attached JAAS cheat sheet has been copied verbatim from this free source.
附带的 JAAS 技巧表中的所有代码都是直接从本 免费资源 复制的。
References / 参考¶
- Oracle JAAS Reference Guide) (Oracle JAAS 参考指南)
- Oracle JAAS: LoginModule Developer's Guide) (Oracle JAAS:LoginModule 开发者指南)