`

JAAS(二)

 
阅读更多
Java认证和授权服务(JAAS)供应器
15.1. 概述
Spring Security提供一个包,可以代理Java认证和授权服务(JAAS)的认证请求。 这个包的细节在下面讨论。
JAAS的核心是登录配置文件。 想要了解更多JAAS登录配置文件的信息,可以查询Sun公司的JAAS参考文档。 我们希望你对JAAS有一个基本了解,也了解它的登录配置语法,这才能更好的理解这章的内容。
15.2. 配置
这个 JaasAuthenticationProvider 通过JAAS认证用户的主体和证书。
让我们假设我们有一个JAAS登录配置文件,/WEB-INF/login.conf, 里边的内容如下:
JAASTest {
    sample.SampleLoginModule required;
};
就像所有的Spring Security bean一样,这个JaasAuthenticationProvider 要配置在application context里。 下面的定义是与上面的JAAS登录配置文件对应的:
<bean id="jaasAuthenticationProvider"
            class="org.springframework.security.providers.jaas.JaasAuthenticationProvider">
  <property name="loginConfig" value="/WEB-INF/login.conf"/>
  <property name="loginContextName" value="JAASTest"/>
  <property name="callbackHandlers">
    <list>
      <bean class="org.springframework.security.providers.jaas.JaasNameCallbackHandler"/>
      <bean class="org.springframework.security.providers.jaas.JaasPasswordCallbackHandler"/>
    </list>
  </property>
  <property name="authorityGranters">
    <list>
      <bean class="org.springframework.security.providers.jaas.TestAuthorityGranter"/>
    </list>
  </property>
</bean>
这个 CallbackHandler和AuthorityGranter会在下面进行讨论。
15.2.1. JAAS CallbackHandler
大多数JAAS的登录模块需要设置一系列的回调方法。 这些回调方法通常用来获得用户的用户名和密码。
在Spring Security发布的时候,Spring Security负责用户交互(通过认证机制)。 因此,现在认证请求使用JAAS代理,Spring Security的认证机制将组装一个Authentication对象,它包含了所有JAASLoginModule需要的信息。
因此,Spring Security的JAAS包提供两个默认的回调处理器,JaasNameCallbackHandler 和 JaasPasswordCallbackHandler。 他们两个都实现了JaasAuthenticationCallbackHandler。 大多数情况下,这些回调函数可以直接使用,不用了解它们的内部机制。
为了需要完全控制回调行为,内部JaasAutheticationProvider使 用一个InternalCallbackHandler封装这个JaasAuthenticationCallbackHandler。 这个InternalCallbackHandler才是 实际实现了JAAS通常的CallbackHandler接口。 任何时候JAASLoginModule被使用的时候,它 传递一个application context里配置的InternalCallbackHandler列 表。 如果这个LoginModule需要回调InternalCallbackHandler,回调会传递封装好的JaasAuthenticationCallbackHandler。
15.2.2. JAAS AuthorityGranter
JAAS工作在主体上。 任何“角色”在JAAS里都是作为主体表现的。 另一方面Spring Security使用Authentication对 象。 每个Authentication对象包含单 独的主体和多个GrantedAuthority[]。 为了方便映射不同的概念,Spring Security的JAAS包包含了AuthorityGranter接口。
一个 AuthorityGranter负责检查JAAS主 体,返回一个String的集合,用来表示分配给这个主体的权限。 对于每一个返回的权限字符串,JaasAuthenticationProvider会 创建一个JaasGrantedAuthority(它实现了Spring Security的GrantedAuthority接口),包含了AuthorityGranter返回的字符串和AuthorityGranter传递的JAAS主体。 JaasAuthenticationProvider获 得JAAS主体,通过首先成功认证用户的证书,使用JAAS的LoginModule,然后 调用LoginContext.getSubject().getPrincipals(), 使用返回的每个主体,传递到每个AuthorityGranter里,最后定义 在JaasAuthenticationProvider.setAuthorityGranters(List)属 性里。
Spring Security没有包含任何产品型的AuthorityGranter, 因为每个JAAS主体都有特殊实现的意义。 但是,这里的单元测试里有一个TestAuthorityGranter, 演示了一个简单的AuthorityGranter实现。



JAAS简介及实例
关键字: 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是如何实现认证的呢?又是如何实现授权的呢?且听我慢慢分解,将其妙处展现给大家。

二 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. }; 

  
将代码编辑通过后执行以下命令:
java -Djava.security.auth.login.config==jaas.config com.SimpleLogin


分享到:
评论

相关推荐

    在JBOSS下自定义JAAS登录模块的示例

    本示例利用JBoss提供的JAAS支持,通过很简单的代码实现了登录和访问控制,能够很好的从一个应用移植到另一个应用(当然仅限JBoss环境),只要修改一些xml和数据库的配置就可以了。 本示例用了一些hibernate的东西读取...

    swbLogin:由SWBDataManager支持的Tomcat JAAS登录模块

    创建JAAS配置文件该配置必须包含模块的必要参数: SWBLoginModule { org.semanticwb.auth.SWBDMLoginModule required debug=true roles="Admin,User,Device" number="1357"; }; 告诉Tomcat文件位于何处: ...

    Java 安全 电子书

    目录 Java安全性 ...1.关于本教程 2.Java安全性编程概念 3.确保消息的完整性 4.保持消息的机密性 ...第二部分:认证与授权 1.关于本教程 2.概念性的概述 3.JAAS中的认证 4.JAAS中的授权 5.JAAS示例 6.结束语和参考资料

    Java高手真经 高级编程篇 下载(二)

     Java Web分布式开发技术:包括JTA事务管理、JAAS验证与授权服务、JNDI命名和目录服务、JMS消息服务、JavaMail邮件服务、WebService、JMX管理、JCA连接器。  Java Web开源技术与框架:包括工作流、规则引擎、搜索...

    Java安全中文版

    这里还详细介绍了如何应用Java安全套接字扩展包(JSSE)实现SSL加密,以及如何利用Java鉴别与授权服务(JAAS)处理鉴别和权限的有关问题。  本书作为一本基础参考书,主要面向为Internet编写应用软件的开发人员。如果...

    Java核心技术II(第8版)

    9.4.1 JAAS 登录模块 9.5 数字签名 9.5.1 消息摘要 9.5.2 消息签名 9.5.3 X.509证书格式 9.5.4 校验签名 9.5.5 认证问题 9.5.6 证书签名 9.5.7 证书请求 9.6 代码签名 9.6.1 JAR文件签名 9.6.2 软件开发者证书 9.7 ...

    Library-Management-System:第二学期,Unitec,编程原理与实践

    图书馆管理系统 第 2 学期,Unitec,编程原理与实践。 网站链接: 到目前为止,我们将使用的技术是:Hibernate ORM & Search。... JAAS(Java 身份验证和授权服务)内置于 Java 中。 用于验证系统用户和权限。

    Java高手真经 高级编程篇 下载(一)

     Java Web分布式开发技术:包括JTA事务管理、JAAS验证与授权服务、JNDI命名和目录服务、JMS消息服务、JavaMail邮件服务、WebService、JMX管理、JCA连接器。  Java Web开源技术与框架:包括工作流、规则引擎、搜索...

    Java高手真经 高级编程篇 下载(三)

     Java Web分布式开发技术:包括JTA事务管理、JAAS验证与授权服务、JNDI命名和目录服务、JMS消息服务、JavaMail邮件服务、WebService、JMX管理、JCA连接器。  Java Web开源技术与框架:包括工作流、规则引擎、搜索...

    Java高手真经 高级编程篇 下载(四)

     Java Web分布式开发技术:包括JTA事务管理、JAAS验证与授权服务、JNDI命名和目录服务、JMS消息服务、JavaMail邮件服务、WebService、JMX管理、JCA连接器。  Java Web开源技术与框架:包括工作流、规则引擎、搜索...

    城市电子政务门户方案设计.docx

    一个完整的门户平台可以有效支持以下的技术要求: 基于J2EE的开放式体系结构 支持国际主流标准Portlet、XML、WSRP、JAAS、JNDI、JCA等 客户端程序和服务端程序相结合,既保障系统的高效灵活扩展性,又降低服务器的...

    Java安全性编程实例(徐迎晓)

    # 第二章 # 解决的主要问题——内容的安全性 # 数据在网上传递怎么样防止被黑客窃取听到? # 硬盘上的文件中有敏感数据,如何防止被黑客看到? # 主要内容 # 本章解决的是数据内容的安全性,介绍Java的加密和解密...

    经典JAVA.EE企业应用实战.基于WEBLOGIC_JBOSS的JSF_EJB3_JPA整合开发.pdf

    第二部分详细讲解了jsf ri、jta、jndi、rmi、jms、javamail、ejb 3的session bean、message driven bean、jpa、jax-ws 2、jaas等java ee知识,这部分知识以jsf+ejb 3+jpa整合开发为重点,通过使用netbeans ide工具...

    从Java走向Java+EE+.rar

    22.1 利用JAAS进行验证和授权 315 22.2 利用JSSE进行安全传输 317 22.3 小结 317 第23章 Java EE的测试 319 23.1 开发者为什么需要学习测试 319 23.2 测试的基本概念 320 23.3 利用JUnit进行单元测试 ...

    spring security 参考手册中文版

    第二部分 架构与实现 73 9.技术概述 73 9.1运行环境 73 9.2核心组件 74 9.2.1 SecurityContextHolder,SecurityContext和认证对象 74 获取有关当前用户的信息 75 9.2.2 UserDetailsService 75 9.2.3授予权力 77 ...

Global site tag (gtag.js) - Google Analytics