加载中…
个人资料
枝叶飞扬
枝叶飞扬
  • 博客等级:
  • 博客积分:0
  • 博客访问:10,756
  • 关注人气:218
  • 获赠金笔:0支
  • 赠出金笔:0支
  • 荣誉徽章:
正文 字体大小:

JAAS的认证与授权

(2011-06-18 18:30:22)
标签:

jaas

认证

授权

logincontext

callback

handler

loginmodule

commit

it

分类: EJB

在应用程序中使用JAAS验证通常会涉及到以下几个步骤:  
  1. 创建一个LoginContext的实例。 
  2. 为了能够获得和处理验证信息,将一个CallBackHandler对象作为参数传送给LoginContext
  3. 通过调用LoginContextlogin()方法来进行验证。  
  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 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 0; 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传递一个CallbackHandlerCallbackHandler又会回调适当的应用程序,从而获得其他认证信息。例如,如果LoginContext在创建CallbackHandler时没有指定用户名和口令,而LoginModule又的确需要这些内容,那么LoginModule就会使用CallbackHandler来回调LoginContext,以重新获得所需要的信息。

为了让验证信息可用于登录,LoginContext还可以向LoginModule传递Subject

JAAS的认证与授权

JAAS初始化序列图

在创建LoginContext时,完成LoginModule的初始化之后,LoginContext就可以调用login( )方法(见图2),它会对Subject进行认证。登录过程需要经过一个由LoginModule组成的菊花链,根据配置文件的内容,每一步都需要一个不同类型的验证信息。配置文件还可以指定可选而非必须的LoginModule的配置。

LoginModule会完成一个两阶段的登录过程:第一个阶段是登录过程调用LoginModulelogin( )方法;第二个阶段是调用commit( )abort( )方法完成登录过程。commit( )过程是当所有其他LoginModule完成自己的login( )方法之后才在登录过程中被调用的,然后最后一个LoginModule会调用commit方法,之后是下一个,依此类推。如果login( )方法不能成功执行,就会调用abort方法来清除已经执行的操作。如果所有必须的commit( )方法都成功完成了,那么登录过程也就成功地完成了。

JAAS的认证与授权

JAAS登录序列图

 

授权过程需要使用在登录过程中确定的验证信息,因此,认证过程通常都是在Subject类中实现的,这并没有什么可奇怪的。Subject类会使用PrivilegedAction类来执行授权的过程。另外,还有一个扩展的PrivilegedAction类对要进行访问控制的资源进行了包装。不管验证信息是否有权对资源进行访问,这都是在安全策略文件中定义的。Java安全管理程序会首先读取适当的安全策略文件,并对权限和验证信息进行分析。然后,安全管理程序会根据这些权限和验证信息使用PrivilegedAction类对资源进行授权(或禁止访问)。如果该资源不允许一个特定的验证信息访问,就会触发一个访问异常。

下面将以一个实例讲解Java胖客户端应用程序如何通过JAAS通过WebLogic Server安全认证并访问受保护资源(如:EJB调用)。

JAAS的认证与授权

1. Java胖客户端应用程序从用户或系统进程获取身份验证信息:用户名、密码与URL(即:WebLogic Server 中的Admin ServerURL地址)

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

0

阅读 收藏 喜欢 打印举报/Report
  

新浪BLOG意见反馈留言板 欢迎批评指正

新浪简介 | About Sina | 广告服务 | 联系我们 | 招聘信息 | 网站律师 | SINA English | 产品答疑

新浪公司 版权所有