JAAS原理

      JAAS是对JCE安全框架的重要补充,通过提供认证用户和确定用户授权来增强JAVA解决方案的动态安全性,使得资源能够得到很好得到保护和控制(JAAS使用动态的安全策略来定义权限,而不是将其静态的嵌入到代码中)。

 

     JAAS采用的是插件的运行方式,一开始就被设计成可插拔的(Pluggable),根据应用的需要,只要配置一下JAAS的配置文件,这些组件即可包含 在我们的应用程序中。使用JAAS包接口,开发者和第三方可以开发一些组件或者BEAN来实现登陆认证,或者通过与使用者或外部的系统的进行交互来访问认 证信息(当然我们可以设计更为稳妥安全的密码学协议)。JAAS提供了一组用于用户鉴别的类和接口,这意味着支持JAAS的应用会要求用户登陆,同时 JAAS提供了另一组用于用户授权的类和接口。在讨论例子之前,先对JAAS API中常用的一些类和接口做个简单的说明。

 

LoginModule :确认用户的合法性(使用CallbackHandler或者其他类方法),并分配访问权限principal给subject;

LoginContext:为了实现用户鉴别,建立相应的环境,从配置文件中导入规则;

CallbackHandler:回调处理器,负责与用户(代码拥有者和执行者)交互,确认其身份的合法性;

Subject:表示登陆处理的目标,即一个被鉴别的用户。并可关联一个或多个pirncipal;

Principal:表示具有访问权限的一个实体,可以看作是可以执行某种操作的证件。

     理解这些类和接口的关系我给个生动的比方:一个军事学校,入学的时候校方(LoginModule)根据学生(Subject)的入学通知来确定其合法 性,这个过程交由某工作人员(CallbackHandler)执行,(CallbackHandler)确认后,(LoginModule)给不同 (Subject)根据其身份发给相关的证件(Principal),有了该证件就可以访问对应的资源,(Subject)根据自己的 (Principal)的级别可以使用和访问学校不同资源。 一个(Subject)的(Principal)如果是士官级,那么可以访问的资源就相对少些,如果是将军级那就多些。当然一个(Subject)可以拥有多个(Principal)。

通过分析我们会发现,JAAS采用的也是身份检查+权限分配模式。因此JAAS的应用也分成两个部分:(1)认证;(2)授权。过程是先认证后根据身份来授权(有歧视的嫌疑的东东,本人可是反歧视人士)。

 

二 JAAS的认证原理

(1) 设置JAAS配置文件,关于配置非常有技巧,跟设置防火墙的过滤规则有得一拼;

(2) 根据JAAS配置文件的条目加载一个或者多个LoginModule(通常一个,也可以变态得使用多个);

(3) 为了管理用户认证的有关过程,将提供一个可选的LoginModule构造函数和一个回调处理器CallbackHandler。如果没有在构造函数中提供回调处理器,系统采用默认设置;

(4) 初始并实例化LoginContext(加载配置规则),如果成功,则调用LoginContext的login方法。无论是否需 要,LoginContext都会去首先读取JAAS配置文件,从中获得要加载的登陆模块信息,其initialize方法将按照配置文件中的相关内容提 供LoginModule运行所需要的信息;

(5) LoginContext的login方法将调用LoginModule的login方法,确定用户身份。该方法将设置相关的回调,并由回调处理器CallbackHandler来管理登陆处理回调;

(6) LoginModule的login方法将负责与用户进行交互(可能是人机交互,也可能是机机交互),如果用户输入信息无效,则该方 法返回FALSE,一次交互过程结束,如果用户输入信息有效,则该方法将设置Principal对象的Subject对象,并返回TRUE;当然 LoginModule也可以将与用户之间的所有交互过程全部委托给处理器CallbackHandler来处理。如果登陆成功, LoginContext将调用LoginModule的commit方法将结果提交给LoginModule实例的内部状态。


 在应用程序中使用JAAS验证通常会涉及到以下几个步骤:

  1. 创建一个LoginContext的实例。

  2. 为了能够获得和处理验证信息,将一个CallBackHandler对象作为参数传送给LoginContext。

  3. 通过调用LoginContext的login()方法来进行验证。

  4. 通过使用login()方法返回的Subject对象实现一些特殊的功能(假设登录成功)。

  下面是一个简单的例子:

      SimpleLogin.java
      

Java代码 
1.package com;  
2. 
3.import javax.security.auth.login.LoginContext;  
4.import javax.security.auth.login.LoginException;  
5. 
6.public class SimpleLogin {  
7.      
8.    public static void main(String[] args) {  
9.          
10.        // 建立登陆上下文,并通过配置文件初始化,在这里配置文件必须与程序同目录  
11.        LoginContext loginContext = null;  
12.        try {  
13.                                             
14.            loginContext = new LoginContext("simple", new SimpleCallbackHandle());  
15.        } catch (LoginException e) {  
16.              
17.            System.out.println(e.getMessage());  
18.        }  
19.          
20.        try {  
21.              
22.            // 如果不抛出异常表示验证成功  
23.            loginContext.login();  
24.        } catch (LoginException e) {  
25.              
26.        }  
27.    }  
28.      
29.} 
   SimpleCallbackHandle.java
   

Java代码 
1.package com;  
2. 
3.import java.io.BufferedReader;  
4.import java.io.IOException;  
5.import java.io.InputStreamReader;  
6.import javax.security.auth.callback.Callback;  
7.import javax.security.auth.callback.CallbackHandler;  
8.import javax.security.auth.callback.NameCallback;  
9.import javax.security.auth.callback.PasswordCallback;  
10.import javax.security.auth.callback.UnsupportedCallbackException;  
11. 
12.public class SimpleCallbackHandle implements CallbackHandler {  
13. 
14.    public void handle(Callback[] callbacks) throws IOException,  
15.            UnsupportedCallbackException {  
16. 
17.        for (Callback callback : callbacks) {  
18. 
19.            if (callback instanceof NameCallback) {  
20.                NameCallback nc = (NameCallback) callback;  
21.                  
22.                System.out.print(nc.getPrompt());  
23.                System.out.flush();  
24.                  
25.                nc.setName((new BufferedReader(new InputStreamReader(  
26.                                System.in))).readLine());  
27.            } else if (callback instanceof PasswordCallback) {  
28.                PasswordCallback pcb = (PasswordCallback) callback;  
29.                  
30.                System.out.print(pcb.getPrompt());  
31.                System.out.flush();  
32.                pcb.setPassword((new BufferedReader(new InputStreamReader(  
33.                        System.in))).readLine().toCharArray());  
34.            }  
35.        }  
36.    }  
37.} 
SimpleLoginModule.java


Java代码 
1.package com;  
2. 
3.import java.io.IOException;  
4.import java.util.Map;  
5. 
6.import javax.security.auth.Subject;  
7.import javax.security.auth.callback.Callback;  
8.import javax.security.auth.callback.CallbackHandler;  
9.import javax.security.auth.callback.NameCallback;  
10.import javax.security.auth.callback.PasswordCallback;  
11.import javax.security.auth.callback.UnsupportedCallbackException;  
12.import javax.security.auth.login.LoginException;  
13.import javax.security.auth.spi.LoginModule;  
14. 
15.public class SimpleLoginModule implements LoginModule{  
16. 
17.    private String userName;  
18.      
19.    private char[] password;  
20.      
21.    private Subject subject;  
22.      
23.    private CallbackHandler callbackHandler;  
24.      
25.    private Map sharedState;  
26.      
27.    private Map options;  
28.      
29.    private String debug;  
30.      
31.    public boolean abort() throws LoginException {  
32.        System.out.println("abort()");  
33.        return false;  
34.    }  
35. 
36.    public boolean commit() throws LoginException {  
37.        System.out.println("commit()");  
38.        return false;  
39.    }  
40. 
41.    public void initialize(Subject subject, CallbackHandler callbackHandler,  
42.            Map sharedState, Map options) {  
43.          
44.        this.subject = subject;  
45.        this.callbackHandler = callbackHandler;  
46.        this.sharedState = sharedState;  
47.        this.options = options;  
48.          
49.        debug = (String)options.get("debug");  
50.    }  
51. 
52.    public boolean login() throws LoginException {  
53.          
54.        Callback[] callbacks = new Callback[2];  
55.        callbacks[0] = new NameCallback("用户名: ");  
56.        callbacks[1] = new PasswordCallback("密码: ", false);  
57.          
58.        try {  
59.              
60.            callbackHandler.handle(callbacks);  
61.            userName = ((NameCallback)callbacks[0]).getName();  
62.            password = ((PasswordCallback)callbacks[1]).getPassword();  
63.              
64.            if(debug.equals("true")){  
65.                System.out.println("你输入的用户名为:" + userName);  
66.                System.out.println("你输入的密码为:" + new String(password));  
67.            }  
68.              
69.            if(userName.equals("callan") && new String(password).equals("callanpass")){  
70.                System.out.println("验证成功");  
71.                return true;  
72.            } else {  
73.                System.out.println("验证失败");  
74.                userName = null;  
75.                password = null;  
76.            }  
77.        } catch (IOException e) {  
78.            e.printStackTrace();  
79.        } catch (UnsupportedCallbackException e) {  
80.            e.printStackTrace();  
81.        }  
82.          
83.        return false;  
84.    }  
85. 
86.    public boolean logout() throws LoginException {  
87.        System.out.println("logout()");  
88.        return false;  
89.    }  
90. 
91.}

 

jaas.config

 

Java代码 
1.simple {  
2.   com.SimpleLoginModule required debug=true;  
3.}; 
simple {
   com.SimpleLoginModule required debug=true;
};
 

  

将代码编辑通过后执行以下命令:

java -Djava.security.auth.login.config==jaas.config com.SimpleLogin

 

 

**简单明了地说明了java验证、授权机制(看到好的文章,就情不自禁的转到自己的空间里了)

 

你可能感兴趣的:(设计模式,bean,配置管理,防火墙,Security)