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

acegi流程分析之一《Acegi 中的HttpSessionEvent 监听机制 窥视Acegi

阅读更多

Acegi 中的 HttpSessionEvent 监听机制 窥视 Acegi 工作流程。

 

Acegi 结合了 Spring 提供了不错的 HttpSessionEvent 监听机制

使用 Acegi HttpSessionEvent 监听机制,我首先要在 web.xml 中增加一个 Listener

org.acegisecurity.ui.session.HttpSessionEventPublisher

有人要问这不是一个 Listener 么,类名应该是一个 *Listener 什么的啊。的确它实现了 javax.servlet.ServletContextListener 接口和 javax.servlet.http.HttpSessionListener 接口。前者是在 web 应用创建时,可以可以通过 ServletContext 来获取一个 Spring ApplicationContext 。后者是在 HttpSession 创建和超时时发布利用 Spring ApplicationContext. publishEvent() 方法发布事件的,注意并不时发布的 HttpSesionEvent ,而是有 HttpSession 作为构造参数,创建了 HttpSessionCreatedEvent HttpSessionDestroyedEvent ,这两个 Event 都是 Spring ApplicationEvent 的子类,这样 Spring 才会处理这些 Event 。事件发布后, Spring 会在上下文查找实现了 ApplicationListener 接口的接口子类来处理这两个 Event

 

到这,你心里或许有些疑惑, HttpSessionEvent 发布了,那个 ApplicationListener 来处理这个 HttpSessionEvent 呢?注意,重要人物出场了。

org.acegisecurity.concurrent. SessionRegistryImpl 出场了。看了它的源代码,你会发现它还实现另外一个接口 org.acegisecurity.concurrent. SessionRegistry

这个定义如下一些方法

 

public interface SessionRegistry {

    public Object[] getAllPrincipals();

    public SessionInformation[] getAllSessions(Object principal, boolean includeExpiredSessions);

    public SessionInformation getSessionInformation(String sessionId);

    public void refreshLastRequest(String sessionId);

    public void registerNewSession(String sessionId, Object principal)

        throws SessionAlreadyUsedException;

    public void removeSessionInformation(String sessionId);

}

这些方法的功能通过看方法名就能知道了。

看一下 SessionRegistryImpl. onApplicationEvent() 方法,看它做了些什么

 

    public void onApplicationEvent(ApplicationEvent event) {

        if (event instanceof HttpSessionDestroyedEvent) {

            String sessionId = ((HttpSession) event.getSource()).getId();

            removeSessionInformation(sessionId);

        }

    }

它怎么只处理 HttpSessionDestoryedEvent ,这就说 SessionRegistryImpl 只处理 HttpSession 的销毁,也就是这又是为什么呢。如果你仔细看了 SessionRegistry 的接口定义,或许能明白一些, SessionRegistryImpl 需要存储客户端用户的 SessionInformation SessionInformation 里面又有什么, SesssionInformation 有四个字段

 

    private Date lastRequest;

    private Object principal;

    private String sessionId;

    private boolean expired = false;

除了 principal ,其他三个字段应该很容易理解,那这个 Principal 是什么东西呢, Principal 可以理解为当前客户端用户的身份信息,这个身份信息可以包含用户名,用户密码,用户在系统里面拥有的权限。 Acegi 提供了一个 UserDetail 来表示用户的身份。

 

public interface UserDetails extends Serializable {

    public GrantedAuthority[] getAuthorities();

    public String getPassword();

    public String getUsername();

    public boolean isAccountNonExpired();

     public boolean isAccountNonLocked();

    public boolean isCredentialsNonExpired();

    public boolean isEnabled();

}

顺便提一下 SessionRegistryImpl 处理 HttpSessionDestoryedEvent 是,只是把这个 HttpSesion 的有关信息也就是 SessionInformation 从存储中移出。

 

 

通过上面的分析,你觉得每当新的 HttpSession 创建时, SessionRegistryImpl 也处理这个 Event 还有意义吗?事实上 SessionRegistryImpl 没有处理 HttpSessionCreatedEvent Acegi 也没有提供其他的 Spring ApplicationListener 来处理这个 HttpSessionCreatedEvent

注意,我们的程序一般并不用直接与 SessionRegistryImpl 打交道,你只需在 Spring 的配置文件定义一个 Bean 就行了,如

 

< bean id = "sessionRegistry" class = "org.acegisecurity.concurrent.SessionRegistryImpl" />

只是如此而已。

 

那么当 HttpSession 创建时, Acegi 并不做处理,还会有其他的咚咚来处理么; SessionRegistryImpl 还需要存储用户的 Principal ,那么什么咚咚与 SessionRegistryImpl 打交道呢?

有,但不过不是 ApplicationListener 了,别忘了, SpringSide 还定义了一系列的 Filter Acegi 来做过滤(详情请见 org.springside.bookstore.plugins.security. applicationContext-security-acegi.xml ),那什么 Filter 与实现了 SessionRegistry 接口的 SessionRegistryImpl 打交道呢?下面我来介绍一下 ConcurrentSessionFilter ,这个 Filter 是与 SessionRegistryImpl 打交道的。我们先看一下该 Filter doFilter() 的方法 ( 截取了部分代码 )

 

    public void doFilter(ServletRequest request, ServletResponse response, FilterChain chain)

        throws IOException, ServletException {

------------------

 

        HttpServletRequest httpRequest = (HttpServletRequest) request;

        HttpServletResponse httpResponse = (HttpServletResponse) response;

 

        HttpSession session = httpRequest.getSession(false);

 

        if (session != null) {

            SessionInformation info = sessionRegistry.getSessionInformation(session.getId());

 

            if (info != null) {

                 if (info.isExpired()) {

                    // Expired - abort processing

                    session.invalidate();

 

                    String targetUrl = httpRequest.getContextPath() + expiredUrl;

//Session 已经过期,转向一个 targetUrl ,比如登陆页面

                    httpResponse.sendRedirect(httpResponse.encodeRedirectURL(targetUrl));

 

                    return;

                } else {

                    // Non-expired - update last request date/time

                    info.refreshLastRequest();

                }

            }

        }

 

        chain.doFilter(request, response);

    }

各位看官可能要问为什么要调用 SessionInformation.isExpired() 来检测通过 HttpSession id 来获取 SessionInformation 是否过期呢,过期 ( 超时 ) SessionInformation 不是由 SessionRegistryImpl 清除掉了吗?

 

如果你能跟我一样发现这个问题,说明看得比较仔细和投入 :)

下面来介绍一下 ConcurrentSessionController 接口,因为 SpringSide 里面用了这个实现,所以一定要介绍下:)。

ConcurrentSessionController 接口有两个方法: public void checkAuthenticationAllowed(Authentication request) public void registerSuccessfulAuthentication(Authentication authentication) 。前一个方法检查当前用户请求的认证 ( 这里是姑且把 Authentication 翻译成认证 ) 是否是系统允许的,如果没有经过允许则抛出 AuthenticationException 异常给 Acegi 处理;后一个方法把认证赋予当前用户。

 

Acegi 提供 ConcurrentSessionController 接口的一个增强实现 ConcurrentSessionControllerImpl ,提供更多的控制策略,比如配置是否允许用户重复登陆,最多允许多少个 HttpSession

下面看下 ConcurrentSessionController 的接口实现 ConcurrentSessionControllerImpl ,不过是我们只看其中一部分, Aecgi 是怎么让 SessionInformation 过期的

 

 

// 允许 HttpSession 超过设定值   

  protected void allowableSessionsExceeded(String sessionId, SessionInformation[] sessions, int allowableSessions,

        SessionRegistry registry) {

        if (exceptionIfMaximumExceeded || (sessions == null)) {

            throw new ConcurrentLoginException(messages.getMessage("ConcurrentSessionControllerImpl.exceededAllowed",

                    new Object[] {new Integer(allowableSessions)}, "Maximum sessions of {0} for this principal exceeded"));

        }

// 检查 SessionRegistryImpl 中最后更新的 SessionInformation

        SessionInformation leastRecentlyUsed = null;

 

        for (int i = 0; i < sessions.length; i++) {

            if ((leastRecentlyUsed == null) || sessions[i].getLastRequest().before(leastRecentlyUsed.getLastRequest())) {

                 leastRecentlyUsed = sessions[i];

            }

        }

// 找到一个倒霉蛋,对不起,我要把你的 SessionInformation 设置为过期,这样 ConcurrentSessionFilter 在处理到你的 SessionInformation 时会让你重新登陆系统

        leastRecentlyUsed.expireNow();

    }

 

 

分析到这里,不禁感叹一句, Acegi 提供了多么贴心的功能,感激得快流泪了。

 

写了这么多,你也看了这么多,快要骂我了,写了这么多,就说了 Acegi 怎么处理 HttpSession 超时,怎么处理每个 HttpSession 中的用户信息,怎么管理 Session 用户,以及那个倒霉蛋,还有那个倒霉蛋转到登陆页面再次输入用户名和密码的。

那用户访问受限资源时, Acegi 又是怎么做的呢。好,各位稍休息一会,我也抽根烟调整下思路。

 

 

 

好,第二部分开始了。 Acegi 怎么保护受限资源的。这里稍微点一下,资源可以分为多种,比如某个类的方法啊, URL 啊,只要写相应的拦截器去处理就 OK 了。拦截器检查到该用户没有权限访问资源,很简单,抛出异常 ( 至于针对方法和 URL 的拦截器是怎么工作的,这部分我们先不讲 )

好戏正式开始 ---Acegi 怎么处理这个异常的。你可以已经想到了,使用 Filter 。对,是 Filter Acegi 定义个 Filter ,用来处理这些异常,这个 Filter org.acegisecurity.ui.ExceptionTranslationFilter ExceptionTranslationFilter

 

 

        try {

            chain.doFilter(request, response);

            if (logger.isDebugEnabled()) {

                logger.debug("Chain processed normally");

  

分享到:
评论

相关推荐

    Acegi例子代码+一个很好的学习Acegi的网址

    4. **过滤器安全链(Filter Security Interceptor)**:Acegi的核心组件之一,它是一个Spring MVC的过滤器,会在请求被处理之前检查用户的权限。如果用户没有足够的权限,过滤器将阻止请求的进一步处理。 5. **频道...

    acegi

    Acegi 是一个在Java开发领域,特别是Spring框架中曾经广泛使用的安全组件,全称为Acegi Security。这个系统为Spring应用程序提供了全面的安全管理解决方案,包括身份验证、授权、会话管理以及安全事件处理等功能。...

    Acegi学习笔记(JAVA系统安全编程时用到)

    在 `web.xml` 中,你需要定义一个名为 `Acegi Filter Chain Proxy` 的过滤器,并将其映射到所有 URL,以便拦截并处理每个请求。过滤器类使用 `FilterToBeanProxy` 创建 `FilterChainProxy` 的实例,`...

    实战Acegi:使用Acegi作为基于Spring框架的WEB应用的安全框架

    Acegi是一个专门为SpringFramework应用提供安全机制的开放源代码项目,全称为Acegi Security System for Spring,当前版本为 0.8.3。它使用了Spring的方式提供了安全和认证安全服务,包括使用Bean Context,拦截器和...

    spring acegi 详细文档

    Spring Acegi是一个安全框架,它为Spring应用提供了一套强大的身份验证和授权机制。这个框架在Spring Security(之前称为Spring Security)之前被广泛使用。在本文中,我们将深入探讨Spring Acegi的核心概念、功能和...

    Acegi框架介绍 acegi安全与认证

    总的来说,Acegi Security(Spring Security)是Spring生态中的重要组成部分,它提供了一种高效且灵活的方式来管理和保护应用程序的安全,确保用户访问控制的准确性和严密性,从而保障系统的稳定运行。通过深入理解...

    spring Acegi例子,很简单的一个acegi实例,容易理解

    3. **过滤器安全链(Filter Security Interceptor)**:Acegi的核心组件之一,它是Servlet过滤器,负责拦截请求并根据配置的策略进行身份验证和授权。 4. **安全性配置(Security Configurations)**:在Spring应用...

    基于java的ACEGI

    AceGI,全称为Acegi Security,是Java领域中一个用于Spring框架的安全组件,它提供了全面的身份验证、授权和会话管理功能。这个框架在早期的Spring版本中非常流行,为开发者构建安全的Web应用程序提供了强大的支持。...

    spring acegi 使用工程demo

    这个"spring acegi 使用工程demo"显然是一个示例项目,旨在帮助开发者理解和实践如何在Spring应用中集成和使用Acegi安全框架。 首先,Acegi是Spring Security的前身,后来被Spring Security所取代,但它的概念和...

    acegi安全策略与CAS整合

    在Web应用中, AceGI提供了一套强大的访问控制和身份验证机制,而CAS则作为外部认证服务器,可以为多个应用提供统一的用户验证。通过整合两者,可以简化用户登录流程,同时加强整体系统的安全性。 1.2 环境: 整合...

    Acegi使用.pdf

    Acegi安全框架通过一系列关键组件来实现这些功能,同时它还具备高度的灵活性,可以与各种认证机制(如容器认证、CASSSO、X509等)进行整合,以适应不同的应用场景。 #### Acegi的关键组件 Acegi安全系统由多个关键...

    权限Acegi的使用

    Acegi Security,现已被Spring Security所取代,是Java EE应用程序中的一个强大且灵活的权限管理框架。它提供了全面的身份验证、授权和访问控制功能,旨在确保企业级应用的安全性。Acegi通过AOP(面向切面编程)的...

    使用acegi控制用户权限实例

    Acegi Security是Spring框架早期的一个安全模块,它提供了全面的基于Spring的应用程序的安全管理功能。在本实例中,我们将深入探讨如何使用Acegi来控制用户的权限。Acegi Security已经被Spring Security替代,但其...

    acegisecurity-1.0.7.zip_.acegisecuri_acegi security 1.0.7_acegi

    Acegi Security是一款在Java平台上广泛使用的安全框架,它为Spring应用程序提供了高级的身份验证、授权和服务保护功能。在本文中,我们将深入探讨Acegi Security 1.0.7版本中的核心概念和关键特性。 首先,我们要...

    菜鸟-手把手教你把Acegi应用到实际项目中(1.2)

    Acegi是Spring Security的前身,它是一个用于Java平台的安全框架,专为Spring应用程序设计。本教程将引导初学者逐步了解如何在实际项目中应用Acegi安全框架,以便为你的Web应用提供强大的身份验证和授权功能。 首先...

    ACEGI

    Acegi Security是一个专门为Spring框架设计的权限控制框架,旨在为基于J2EE的企业级应用程序提供全面的安全服务。这个框架解决了J2EE规范中安全性配置不便于移植的问题,使得应用程序的安全设置能够在不同服务器环境...

    acegi-security-tiger-1.0.0-RC2.jar.zip

    Acegi Security是一个已退役的安全框架,它为Java平台上的Spring框架提供了全面的身份验证和授权服务。这个"acegi-security-tiger-1.0.0-RC2.jar.zip"压缩包包含的是Acegi Security的一个早期版本——1.0.0 Release ...

    Acegi-spring安全框架

    Acegi-Spring安全框架是一个专为基于Spring的企业应用设计的安全框架,现在被称为Spring Security。它提供了声明式的安全访问控制,允许开发者在Spring容器中配置安全相关的Bean,利用Spring的依赖注入(IoC)和面向...

    实战Acegi:使用Acegi作为基于Spring框架的WEB应

    本实战教程将深入探讨如何将Acegi Security集成到Spring框架中,构建一个安全的WEB应用程序。 首先,我们需要理解Acegi Security的核心概念。Acegi Security基于Spring AOP(面向切面编程)原理,允许开发者通过...

    acegi使用说明acegi原理及如何与spring、hibernate结合

    Acegi安全系统,是一个用于Spring Framework的安全框架,能够和目前流行的Web容器无缝集成。它使用了Spring的方式提供了安全和认证安全服务,包括使用Bean Context,拦截器和面向接口的编程方式。因此,Acegi安全...

Global site tag (gtag.js) - Google Analytics