`
dragon0929
  • 浏览: 77669 次
  • 性别: Icon_minigender_1
  • 来自: 北京
文章分类
社区版块
存档分类
最新评论

在JBoss中自己定义JAAS登录模块处理登录事件

阅读更多

在我心目中理想的登录模块应该是这样的,我可以通过配置文件将一些事交给应用服务器的JAAS去处理,但是有必要时我也能够通过重载某些方法拦截登录处理的信息来达到自己的某些目的,比如记录登录事件、读取登录用户的信息放到session中,甚至是再加上一个处理验证码。这些能够实现吗?在Tomcat中好象不行,但是在Jboss中呢?
       由于一直没有时间去解决在JAAS中集成自己编写的验证处理模块的技术,我上一篇介绍的方法在我的项目中用了半年,等我把其他紧要的事情了结之后又回过头来琢磨登录模块的事了。
       我反反复复看了login-config.xml文件,我对这一段产生了一些想法:
<login-module code = "org.jboss.security.auth.spi.DatabaseServerLoginModule"
             flag = "required">
       我能不能继续 org.jboss.security.auth.spi.DatabaseServerLoginModule,然后把这个code的值替换为我自己编写的类呢?Jboss既然提供了这么灵活的配置,那么说理论上应该是可行的,于是我又拿过来Jboss的源代码,仔细地了解了登录方面的一些接口和类,尤其是这个DatabaseServerLoginModule类更是把每一行代码都反复的研究过,我试着编写了一个 com.benjamin.commons.security.LoginModule类,并且重载了login函数和initialize函数,加入了一些测试代码,试验了几次测试结果之后决定从重载login函数着手。这个函数是这样定义的:
public boolean login() throws LoginException ;
       在这个函数里可以通过 this.getUsername()来取得登录的用户名,然后根据用户名从数据库读取用户信息也没问题,但是session呢?我怎么取得 session对象并往里面加东西?这个类即没有继承servlet也没有任何属性或参数与request有关,看来这个session是没办法获取了?我很不甘心就这样放弃,在google上输入了各种关键字来查找有用的信息,国内介绍JAAS的资料本来就少之又少,更别说这牛角尖一样偏门的方面了,终于网络不负有心人,我在一个国外的论坛上找到了一点资料,原来在Jboss中可以通过PolicyContext这个类来获取应用服务器的安全性方面的上下文,其中就包括获取HttpServletRequest,具体方法是这样的:
 
HttpServletRequest request = 
                     (HttpServletRequest)PolicyContext.getContext(WEB_REQUEST_KEY);
 
后来我更发现只要是在Jboss容器运行的任何类都可以通过这种方式获取request对象。
有了request获取session当然就不成问题了:
HttpSession session=request.getSession(true);
最后我的这个login函数变成了这样:
 
    public boolean login() throws LoginException {
       boolean loginAccepted =false;
       HttpServletRequest request = null;
    
       try {
//         System.out.println("开始调用JAAS验证 ...");
           request = (HttpServletRequest)PolicyContext.getContext("javax.servlet.http.HttpServletRequest" );
           HttpSession session=request.getSession(true);
       //  String loadPath = this.getClass().getProtectionDomain().getCodeSource().getLocation().toString();
           
//         log.info("开始调用JAAS验证 ...");
           loginAccepted = super.login();
           log.info("已通过JAAS验证,开始获取登录用户信息");
       } catch (LoginException e) {
           request.setAttribute("ex", e);
           LoginException ex=new& nbsp;LoginException("用户" + this.getUsername() +"登录失败:" + e.getMessage());
           log.error(e);
           throw ex;
       } catch (PolicyContextException e) {      
           LoginException ex=new& nbsp;LoginException("获取request失败:" + e.getMessage());
           log.error(ex);
           request.setAttribute("ex", ex);
           throw ex;
       }
       
       if(loginAccepted) {         
           try {
               String userName=this.getUsername();
 
              //根据登录用户名读取用户信息保存到session中
                if (loginBo.login(userName,request)) {
                    log.info(userName + "  登录成功.");
                }
                else{
                      log.error(userName + " 登录失败!");           
                      throw new LoginException(" 登录失败,无法从数据库获取用户信息!");
                }                      
           }          
           catch(Exception e) {
              LoginException ex=new& nbsp;LoginException("登录失败:" + e.getMessage());
              log.error(ex);
              request.setAttribute("ex", ex);
               throw ex;
           }       
           
       }
       return loginAccepted;
    }
 
    然后我把login-config.xml的相关配置改成了这个样子:
 
 <application-policy name = "jbosstest">
       <authentication>
                   <!--  重载org.jboss.security.auth.spi.DatabaseServerLoginModule的类 -->
          <login-module code = "com.benjamin.commons.security.LoginModule"
             flag = "required">
             <module-option name = "dsJndiName">java:/testds</module-option>
             <module-option name = "principalsQuery">SELECT PASSWORD FROM REL_PUB_OPERATOR  WHERE LOGINID=?</module-option>
             <module-option name = "rolesQuery">SELECT ROLENAME,’Roles’ FROM VREL_ROLE WHERE LOGINID=?</module-option>
             <module-option name="hashAlgorithm">MD5</module-option>
<module-option name="hashEncoding">base64</module-option>          </login-module>
       </authentication>
    </application-policy>
 
    这样我想实现的读取用户信息到session的功能就实现了,但是我想更灵活更通用一点,我在这个项目中用的loginBo的类和其中的login(userName,request)方法很可能在其他项目中就不一样了,我应该也通过配置来实现自定义自己的登录完毕后的处理类。我在前面几次测试的过程中发现<login-module … /> 的值是可以在 loginModule类的initialize函数里通过options.get(String)方法获取得到,于是我改了改登录配置文件,加了一行:
    <module-option name="loginBo">com.system.business.LoginBo</module-option>
 
变成这样:
 
<application-policy name = "jbosstest">
       <authentication>
                   <!--  重载org.jboss.security.auth.spi.DatabaseServerLoginModule的类 -->
          <login-module code = "com.benjamin.commons.security.LoginModule"
             flag = "required">
             <module-option name = "dsJndiName">java:/testds</module-option>
             <module-option name = "principalsQuery">SELECT PASSWORD FROM REL_PUB_OPERATOR  WHERE LOGINID=?</module-option>
             <module-option name = "rolesQuery">SELECT ROLENAME,’Roles’ FROM VREL_ROLE WHERE LOGINID=?</module-option>
             <module-option name="hashAlgorithm">MD5</module-option>
                                                         <module-option name="hashEncoding">base64</module-option>
                            <module-option name="loginBo">com.benjamin.system.business.LoginBo</module-option>       
          </login-module>       
</authentication>
  </application-policy>
 
然后又在我的LoginModule类里重载了initialize函数:
 
    public void initialize(Subject subject,CallbackHandler callbackHandler,Map sharedState,Map options){
       super.initialize(subject, callbackHandler, sharedState, options);
       if(options.get("loginBo")!=null){
           try {
               loginBo=(ILoginBo)Class.forName(options.get("loginBo").toString()).newInstance();
           } catch (InstantiationException e) {
              log.error(e);
           } catch (IllegalAccessException e) {
              log.error(e);
           } catch (ClassNotFoundException e) {
              log.error("没有找到loginBo类:" + e);
           }
       }
    }
 
这样我就可以很灵活地通过配置实现代码的移植重用,在其它项目里只要重新实现一个loginBo类并修改配置<module-option name="loginBo">为这个类就可以了。
完成之后重新发布到jboss上,运行Jboss,打开登录页面,登录成功,非常完美!
按理这样就算大功告成了,但是当我再次登录的时候发现登录后转向的页面出了一些错误,session里读出来的值都是null,再试了几次,换另外一个用户名登录又是好的,但退出后再次用这个用户名登录时就不行了。这个问题困扰了我好几天,我感觉应该是Jboss保存了登录用户的信息在缓冲区导致一些方面冲突。但是怎么解决呢?
最后还是在网上找到了解决办法,看来离开网络我是没办法再混下去了。
修改JBOSS安装目录下的server\default\deploy\security-service.xml文件,找到这样的一个节点
 <mbean code="org.jboss.security.plugins.JaasSecurityManagerService"
      name="jboss.security:service=JaasSecurityManager">
<attribute name="DefaultCacheTimeout">60</attribute>
<attribute name="DefaultCacheResolution">600</attribute>
 </mbean>
 
将DefaultCacheTimeout和DefaultCacheResolution的值都改为0,即不将登录信息保存到缓冲区,其它地方不变,修改完后这两个节点应该是这样的:
 
<attribute name="DefaultCacheTimeout">0</attribute>
<attribute name="DefaultCacheResolution">0</attribute>
 
   重启Jboss,登录,没问题,再次登录也没问题,经过多次测试后发现这一招果然管用,我用的Jboss版本是4.0.3SP1,后来我在布署其它版本的Jboss时发现没有security-service.xml文件,但是我在这个版本的Jboss的主目录下的server\default\conf\jboss-service.xml配置文件里也找到了同样的DefaultCacheTimeout和 DefaultCacheResolution配置,照样修改为0,运行以后发现完全正常。
       至此我想实现的功能基本上都可以实现了,我之所以加上一个“基本上”,是因为我前面还提到了一个加验证码的功能,我试过几次没有成功,因为我在登录模块里只能获取到页面提交的用户名和密码信息,我试过加上一个textbox来填写验证码,但是不知道在哪里能取得出来,前面所提的方法里获取的request里是取不到,不知道还有什么其它方式。希望有兴趣的朋友可以自己去试一下,试出来了别忘了告诉我。

分享到:
评论

相关推荐

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

    设置DefaultCacheTimeout,DefaultCacheResolution的值为0,这个我就不多说了,请参阅我的上一篇 &lt;br&gt;文章《在JBoss中自己定义JAAS登录模块处理登录事件》。 &lt;br&gt;6.配置完后将TestLoginMoudle.war复制到你的...

    JBOSS security using JAAS

    - **模块**:JBOS支持多种JAAS模块,如LDAP、Database、Certificate等,这些模块负责实际的认证过程。 3. **JAAS配置实例** - **LDAP认证**:JBOS可以通过连接到LDAP服务器进行用户认证,配置包括指定 LDAP URL、...

    JAAS认证与授权教程

    在`JavaSecurity2-source.rar`中,可能包含了示例代码,用于演示如何创建自定义的登录模块以及如何配置和使用JAAS。这些代码可以帮助理解JAAS的工作机制,并为实际开发提供参考。 在实际应用中,我们可能会遇到多种...

    Jboss安全性配置.pdf

    安全性域定义了多个JAAS登录模块,用于处理特定的认证任务。当应用需要启用安全性时,可以通过在jboss.xml或jboss-web.xml等部署描述符中指定相应的安全性域。 以JMX控制台为例,这是一个可以全面管理JBoss服务器的...

    JBOSS4设置控制台jmx-console登录密码

    下面,我们将深入探讨如何在JBOSS4中配置jmx-console的登录密码,确保系统安全的同时,也能够方便地进行管理和监控。 ### JBOSS4中jmx-console密码设置详解 #### 1. **定位jmx-console部署位置** 首先,jmx-...

    JAAS in web applications, 9 of JAAS in Action

    综上所述,JAAS在Web应用程序中的应用涉及到许多关键的组件和流程,包括身份验证、授权、登录模块的实现以及与Servlet容器的集成。理解这些概念并正确地应用它们对于构建安全的Web应用至关重要。通过阅读《JAAS in ...

    JBoss 3.0 Quick Start Guide

    - **`org.jboss.security.auth.login.XMLLoginConfig`**:通过 XML 文件定义 JAAS 登录模块和策略。 **JAAS 登录模块** - **`org.jboss.security.auth.spi.UsersRolesLoginModule`**:基于简单的用户名/密码认证。 ...

    JBoss加密之SedureIdentityLoginModule(数据源连接方式)

    SedureIdentityLoginModule是JBoss提供的一个安全模块,用于处理用户登录时的身份验证过程。在JBoss中,LoginModule是实现用户认证策略的关键组件,它定义了如何验证用户的身份以及获取用户的角色信息。 首先,我们...

    jboss安全性 jboss设置安全性

    这里定义了一个名为`jmx-console`的应用策略,并使用了`UsersRolesLoginModule`登录模块来处理用户的认证过程。该模块通过指定的属性文件来查找用户信息和角色分配。 此外,还需要创建两个属性文件`props/jmx-...

    jaas文档

    - 配置JAAS通常涉及到在JBoss的应用部署目录下创建`login-config.xml`文件来定义登录模块和安全领域(Security Domain)。 - 在`login-config.xml`中,可以通过指定不同的登录模块来支持多种认证方式,如数据库...

    Jboss In Action

    理解如何组织和声明模块,以及如何在`module.xml`文件中配置它们,是提升JBoss使用效率的关键。在这个压缩包中,可能会包含不同模块的示例,帮助你学习这一部分知识。 JBoss EAP(Enterprise Application Platform...

    jboss7 + EJB3

    在JBOSS7中部署EJB3应用,通常需要以下步骤: - 创建EJB项目:使用Maven或Gradle创建包含EJB3组件的Java项目。 - 编写EJB:使用注解如`@Stateless`、`@Stateful`、`@Singleton`、`@MessageDriven`来定义不同类型...

    JBoss学习全集多本书整合

    JBoss支持多种认证方式,如JaAS(Java Authentication and Authorization Service),可以通过修改`standalone/configuration/standalone.xml`或`domain/configuration/domain.xml`中的安全域配置进行设定。...

    jboss5服务器2

    在本篇中,我们将深入探讨JBoss5的核心特性、配置以及在分布式环境中的应用。 1. **核心特性** - **EJB3支持**:JBoss5完全支持Java EE 5规范中的Enterprise JavaBeans 3.0,简化了EJB的开发和部署,引入了无状态...

    jaas in action

    6. **实际应用示例**:每个章节可能都包含实际应用的示例,例如在Web应用、企业级应用服务器(如JBoss、GlassFish)中如何使用JAAS进行安全配置,以及如何处理会话管理和SSO(单点登录)。 7. **案例研究与最佳实践...

    jboss-4.2.3.GA_下的jboss-4.2.3.GA_下的

    7. **模块化设计**:JBoss AS的模块化架构使得组件可以独立部署和更新,提高了灵活性。 【压缩包文件解析】 1. **readme.html**:通常包含关于软件的安装、配置和使用的基本信息,是开始了解JBoss AS 4.2.3.GA的...

    JBoss用户操作指南

    - **模块系统**:理解JBoss模块化设计,便于组件管理和升级。 - **开发插件**:如使用Maven插件进行自动化构建和部署。 9. **故障排查** - **日志分析**:查看`server.log`等日志文件,定位错误信息。 - **调试...

    jboss-4.2.2.GA

    2. **模块化架构**:JBoss采用模块化设计,将各种服务和组件打包在独立的JAR或WAR文件中,使得配置和管理更为灵活。 3. **热部署**:允许开发者在运行时更新应用程序,无需重启服务器,提高了开发效率。 4. **EJB ...

    JBOSS架構分析

    为了更深入地理解JBoss内部的工作机制,并为其性能优化提供参考依据,本项目将重点分析JBoss应用服务器的关键组成部分:JBoss EJB容器、JBoss命名服务(NS)、JBoss事务处理(TX)以及JBoss CMP组件。 #### 2. ...

    基于JBOSS的J2EE开发

    在IT行业中,JBOSS作为一款开源的Java应用服务器,是基于J2EE(Java 2 Platform, Enterprise Edition)标准的平台,广泛应用于构建和部署企业级应用。本主题将深入探讨“基于JBOSS的J2EE开发”,旨在帮助开发者理解...

Global site tag (gtag.js) - Google Analytics