在应用程序中使用JAAS验证通常会涉及到以下几个步骤:
1. 创建一个LoginContext的实例。
2. 为了能够获得和处理验证信息,将一个CallBackHandler对象作为参数传送给LoginContext。
3. 通过调用LoginContext的login()方法来进行验证。
4. 通过使用login()方法返回的Subject对象实现一些非凡的功能(假设登录成功)。
下面是一个简单的例子:
LoginContext lc = new LoginContext("MyExample");
try {
lc.login();
} catch (LoginException) {
// Authentication failed.
}
// Authentication sUCcessful, we can now continue.
// We can use the returned Subject if we like.
Subject sub = lc.getSubject();
Subject.doAs(sub, new MyPrivilegedAction());
在运行这段代码时,后台进行了以下的工作。
1. 当初始化时,LoginContext对象首先在JAAS配置文件(即java.security.auth.login.config)中找到MyExample项,然后更具该项的内容决定该加载哪个LoginModule对象。
2. 在登录时,LoginContext对象调用每个LoginModule对象的login()方法。(public interface LoginMoudule(){ boolean login(){}; boolean commit(); boolean abort(); boolean logout(); })
3. 每个login()方法进行验证操作或获得一个CallbackHandle对象。
4. CallbackHandle对象通过使用一个或多个CallBack方法同用户进行交互,获得用户输入。
5. 向一个新的Subject对象中填入验证信息。
登录环境
下面是LoginContext
public final class LoginContext {
public LoginContext(String name) {}
public void login(){}
public void logout(){}
public Subject getSubject(){}
}
LoginContext是一种用于设置登录过程的 Java类,它进行实际的登录,如果登录成功,获取Subject。它有如下四种主要方法:
· LoginContext("JAASExample", newUsernamePasswoerdCallbackHandler())是构造器。它把 java.security.auth.login.config指定的配置文件中使用的字符串作为其第一个参数,把执行实际任务的回调处理程序作为其第二个参数。(接下来,我们将讨论回调处理程序。)
· login(),它根据配置文件中指定的规则实际尝试登录。
· getSubject(),如果登录总体成功,它返回经认证的 Subject。
· logout(),它向 LoginContext 注销 Subject。
回调处理程序
登录使用回调处理程序来获取用户的认证信息。CallbackHandler是在LoginContext对象的构造函数中指定的。从登录模块调用的处理程序的handle()方法将Callback数组对象作为其参数。在登录期间,处理程序遍历Callback数组。handle()方法检查Callback对象的类型并执行适当的用户操作。Callback类型如下:
· NameCallback
· PasswordCallback
· TextInputCallback
· TextOutputCallback
· LanguageCallback
· ChoiceCallback
· ConfirmationCallback
在某些应用程序中,因为 JAAS将用于与操作系统的认证机制相互操作,所以不需要任何用户交互。在这种情况下,LoginContext对象中的CallbackHandler参数将是空的。
回调处理程序代码
下面是一个使用UsernamePasswordCallbackHandler的代码。它由AlwaysLoginModule调用一次(仅一次回调以获取用户标识),由PasswordLoginModule调用一次(两次回调以获取用户标识和密码)。
importjava.io.BufferedReader;
importjava.io.IOException;
importjava.io.InputStreamReader;
importjavax.security.auth.callback.Callback;
importjavax.security.auth.callback.CallbackHandler;
importjavax.security.auth.callback.NameCallback;
importjavax.security.auth.callback.PasswordCallback;
importjavax.security.auth.callback.UnsupportedCallbackException;
// This class implements a username/password callback handler that gets
// information from the user public class
publicclassUsernamePasswordCallbackHandler implements CallbackHandler {
// The handle method does all the work and iterates through the array
// of callbacks, examines the type, and takes the appropriate user
// interaction action.
public void handle(Callback[] callbacks)throws UnsupportedCallbackException, IOException {
for (int i = 0; i < callbacks.length; i++) {
Callback cb = callbacks[i]; //
// Handle username aquisition
if (cb instanceof NameCallback) {
NameCallback nameCallback = (NameCallback) cb;
System.out.print(nameCallback.getPrompt() + "? ");
System.out.flush();
String username = new BufferedReader(new InputStreamReader(System.in)).readLine();
nameCallback.setName(username);
// Handle password aquisition
} else if (cb instanceof PasswordCallback) {
PasswordCallback passwordCallback = (PasswordCallback) cb;
System.out.print(passwordCallback.getPrompt() + "? ");
System.out.flush();
String password = new BufferedReader(new
InputStreamReader(System.in)).readLine();
passwordCallback.setPassword(password.toCharArray());
}
总体过程:
JAAS首先使用一个LoginContext类来查找配置文件中的内容,这些内容可以用来对LoginModules进行初始化(见图1)。所有LoginContext没有指定的初始化参数都会包含在配置文件中。LoginContext还会向LoginModule传递一个CallbackHandler,CallbackHandler又会回调适当的应用程序,从而获得其他认证信息。例如,如果LoginContext在创建CallbackHandler时没有指定用户名和口令,而LoginModule又的确需要这些内容,那么LoginModule就会使用CallbackHandler来回调LoginContext,以重新获得所需要的信息。
为了让验证信息可用于登录,LoginContext还可以向LoginModule传递Subject。
![JAAS的认证与授权 JAAS的认证与授权]()
图1 JAAS初始化序列图
在创建LoginContext时,完成LoginModule的初始化之后,LoginContext就可以调用login( )方法(见图2),它会对Subject进行认证。登录过程需要经过一个由LoginModule组成的菊花链,根据配置文件的内容,每一步都需要一个不同类型的验证信息。配置文件还可以指定可选而非必须的LoginModule的配置。
LoginModule会完成一个两阶段的登录过程:第一个阶段是登录过程调用LoginModule的login( )方法;第二个阶段是调用commit( )或abort( )方法完成登录过程。commit( )过程是当所有其他LoginModule完成自己的login( )方法之后才在登录过程中被调用的,然后最后一个LoginModule会调用commit方法,之后是下一个,依此类推。如果login( )方法不能成功执行,就会调用abort方法来清除已经执行的操作。如果所有必须的commit( )方法都成功完成了,那么登录过程也就成功地完成了。
![JAAS的认证与授权 JAAS的认证与授权]()
图2 JAAS登录序列图
授权过程需要使用在登录过程中确定的验证信息,因此,认证过程通常都是在Subject类中实现的,这并没有什么可奇怪的。Subject类会使用PrivilegedAction类来执行授权的过程。另外,还有一个扩展的PrivilegedAction类对要进行访问控制的资源进行了包装。不管验证信息是否有权对资源进行访问,这都是在安全策略文件中定义的。Java安全管理程序会首先读取适当的安全策略文件,并对权限和验证信息进行分析。然后,安全管理程序会根据这些权限和验证信息使用PrivilegedAction类对资源进行授权(或禁止访问)。如果该资源不允许一个特定的验证信息访问,就会触发一个访问异常。
下面将以一个实例讲解Java胖客户端应用程序如何通过JAAS通过WebLogic Server安全认证并访问受保护资源(如:EJB调用)。
![JAAS的认证与授权 JAAS的认证与授权]()
1. Java胖客户端应用程序从用户或系统进程获取身份验证信息:用户名、密码与URL(即:WebLogic Server 中的Admin Server的URL地址)
2. Java胖客户端应用创建包含身份验证信息的CallbackHandler。
a. Java胖客户端应用使用LoginContext类将CallbackHandler传送给UsernamePassworldLoginModule。
loginContext = new LoginContext("Sample",new SampleCallbackHandler(username, password, url));……loginContext.login();
这里Sample是如何来得呢?我们来看段Ant脚本
Appending "login.config.url.1=file:${java.home}/lib/security/sample_jaas.config" to ${java.home}/lib/security/java.security login.config.url.1=file:$${java.home}/lib/security/sample_jaas.config
以上脚本做两个动作:
一是将sample_jaas.config复制到${java.home}/lib/security目录下
二是在${java.home}/lib/security/java.security文件后面追加login.config.url.1=file:$${java.home}/lib/security/sample_jaas.config语句
login.config.url.1的注释:# Default login configuration file,这里比较清楚是什么意思了吧。
sample_jaas.config内容如下:
Sample { weblogic.security.auth.login.UsernamePasswordLoginModule required debug=false;};
注:$java.home对应的是JRE目录
b. UsernamePasswordLoginModule的真正作用是将包含身份验证信息(即:用户名、密码、URL)的CallbackHandler 传送给WebLogic Server RMI容器。UsernamePasswordLoginModule对于编程人员来说是透明的,它实际上是被隐藏在LoginContext后面了。
3. WebLogic Server RMI容器访问WebLogic安全框架,将包含身份验证信息的客户端CallbackHandler传入安全框架。
4. WebLogic Server安全框架可以配置多个身份验证提供程序(即:Authentication Provider),WebLogic 安全框架将为每个身份验证提供程序创建一个包含身份验证信息CallbackHandler(这里和CallbackHandler已经与客户端传入的 CallbackHandler无关了)
5. WebLogic 安全框架可调用与身份验证提供程序相关联的 LoginModule(也就是专为处理身份验证信息设计的 LoginModule)。LoginModule 尝试使用身份验证信息对客户端进行身份验证。
6. 如果通过身份验证,则会发生下列情况:
委托人验证提供程序对委托人(用户和组),即:Principal 进行签名,以确保其在编程服务器调用之间的真实性。LoginModule 将签名的委托人与主题(Subject)相关联,主题表示正在进行身份验证的用户或系统。
WebLogic 安全框架将身份验证状态返回给Java胖客户端应用程序,Java胖客户端应用程序则从 WebLogic 安全框架中检索已通过身份验证的主题。
代码如下:
Subject subject = loginContext.getSubject();SampleAction sampleAction = new SampleAction(url);Security.runAs(subject, sampleAction);
部分来自:http://joshuafan.blogbus.com/logs/10914307.html
加载中,请稍候......