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


      今天就讲个ConcurrentSessionFilter

    Acegi 1.x版本中,控制并发HttpSessionRemember-Me认证服务不能够同时启用,它们之间存在冲突问题,这是版本的一个Bug,希望他们尽快改进!!关于这方面的资料,网上很多有说,不明白的朋友可以去了解了解。

     

    在一些应用场合,企业可能需要限制同一帐号在同一时间登录到同一Web应用的次数,即控制并发HttpSession的数量。比如,在同一时间,只允许javaee/password用户在服务器存在一个或若干个活动HttpSessionAcegi内置了HttpSession的并发控制支持,为我们提供了方便。为了启用这一企业特性,开发者必须完成如下几方面的配置。

     

    1、将concurrentSessionFilter添加到filterChainProxy

    Xml代码 复制代码 收藏代码
    1. <bean id="filterChainProxy"  
    2.     class="org.acegisecurity.util.FilterChainProxy">  
    •     <property name="filterInvocationDefinitionSource">  
    •         <value>  
    •             CONVERT_URL_TO_LOWERCASE_BEFORE_COMPARISON   
    •             PATTERN_TYPE_APACHE_ANT   
    •             /**=concurrentSessionFilter,httpSessionContextIntegrationFilter,logoutFilter,authenticationProcessingFilter,anonymousProcessingFilter,exceptionTranslationFilter,filterInvocationInterceptor   
    •         </value>  
    •     </property>  
    • </bean>  
    <bean id="filterChainProxy"
    	class="org.acegisecurity.util.FilterChainProxy">
    	<property name="filterInvocationDefinitionSource">
    		<value>
    			CONVERT_URL_TO_LOWERCASE_BEFORE_COMPARISON
    			PATTERN_TYPE_APACHE_ANT
    			/**=concurrentSessionFilter,httpSessionContextIntegrationFilter,logoutFilter,authenticationProcessingFilter,anonymousProcessingFilter,exceptionTranslationFilter,filterInvocationInterceptor
    		</value>
    	</property>
    </bean>

     

     

    2、配置ConcurrentSessionFilter

    控制并发HttpSession的过滤器,concurrentSessionFilter暴露了sessionRegistryexpiredUrl属性,sessionRegistry引用一个HttpSession注册器,这一注册器动态维护了登录到这一Web应用的所有HttpSession信息。

    ConcurrentSessionFilter起到两个作用:

    第一、对每个请求它都会调用org.acegisecurity.concurrent.SessionRegistry.refreshLastRequest(String)方法,这样保证所有已注册的会话总是有正确的最后修改时间。

    第二、它会从SessionRegistry为每个请求返回org.acegisecurity.concurrent.SessionInformation会话信息,并且检查session是否已标记为过期。如果已标记为过期,那么该session将会被invalidate()掉。

    Xml代码 复制代码 收藏代码
    1. <bean id="concurrentSessionFilter"  
    2.     class="org.acegisecurity.concurrent.ConcurrentSessionFilter">  
    3.     <!-- 每次HttpSession开始或者结束的时候,web.xml中的HttpSessionEventPublisher都会发布一个 ApplicationEvent事件到Spring的ApplicationContext。这是至关重要的,因为这个机制允许在session结束的时候,SessionRegistryImpl会得到通知。这解释了为什么我们需要在ConcurrentSessionFilter中指向 SessionRegistryImpl的实例。-->  
    4.     <property name="sessionRegistry" ref="sessionRegistry"></property>  
    5.     <!-- 如果concurrentSessionController的exceptionIfMaximumExceeded属性设置为true,那么一旦并发HttpSession数量超过限额,将会重定向到expiredUrl指定的路径 -->  
    6.     <property name="expiredUrl">  
    7.         <value>/concurrentError.jsp</value>  
    8.     </property>  
    9. </bean>  
    10. <!-- 注意,我们的程序一般并不用直接与SessionRegistryImpl打交道,你只需在Spring的配置文件定义一个Bean就行了 -->  
    11. <bean id="sessionRegistry"  
    12.     class="org.acegisecurity.concurrent.SessionRegistryImpl">  
    13. </bean>  
    <bean id="concurrentSessionFilter"
    	class="org.acegisecurity.concurrent.ConcurrentSessionFilter">
    	<!-- 每次HttpSession开始或者结束的时候,web.xml中的HttpSessionEventPublisher都会发布一个 ApplicationEvent事件到Spring的ApplicationContext。这是至关重要的,因为这个机制允许在session结束的时候,SessionRegistryImpl会得到通知。这解释了为什么我们需要在ConcurrentSessionFilter中指向 SessionRegistryImpl的实例。-->
    	<property name="sessionRegistry" ref="sessionRegistry"></property>
    	<!-- 如果concurrentSessionController的exceptionIfMaximumExceeded属性设置为true,那么一旦并发HttpSession数量超过限额,将会重定向到expiredUrl指定的路径 -->
    	<property name="expiredUrl">
    		<value>/concurrentError.jsp</value>
    	</property>
    </bean>
    <!-- 注意,我们的程序一般并不用直接与SessionRegistryImpl打交道,你只需在Spring的配置文件定义一个Bean就行了 -->
    <bean id="sessionRegistry"
    	class="org.acegisecurity.concurrent.SessionRegistryImpl">
    </bean>

     

     

    3、配置HttpSessionEventPublisher

          SessionRegistry的实现类是SessionRegistryImplSessionRegistryImpl实现了ApplicationListener,而且它会负责应对HttpSessionDestroyedEvent事件。一旦SessionRegistryImpl接收到HttpSessionDestroyedEvent事件,则它会把触发这一事件的HttpSession的相关信息从当前注册器中清除掉。因此,HttpSessionEventPublisher的配置工作显得格外重要。在web.xml中添加

    Xml代码 复制代码 收藏代码
    1. <listener>  
    2.     <listener-class>  
    3.         org.acegisecurity.ui.session.HttpSessionEventPublisher   
    4.     </listener-class>  
    5. </listener>  
    <listener>
    	<listener-class>
    		org.acegisecurity.ui.session.HttpSessionEventPublisher
    	</listener-class>
    </listener>

     

    (个人发现,如果不添加这个listener,仍然能实现并发控制,很奇怪。清楚这方面的朋友就回复教教我,谢谢!)

     

    4、配置concurrentSessionController

    并发HttpSession控制器, concurrentSessionController只需要一个sessionRegistry实例的属性,但它应用时还使用了maximumSessions属性,把它赋值为1。在ConcurrentSessionControllerImpl的源代码中,这个值初始值其实也是1

    *它的用法和用处是这样的:*

    (1)可以给它赋值-1,那么将不会限制并发登录。

    (2)可以给它赋大于0值,这个数字限制相同用户名同时成功并发登录同一个web应用的次数。

    注意:不可以给它赋值为0,这是不允许的。

    例如,如果这个值是3,那么用户名为javaee的用户可以同时在3个地点同时成功登录进web应用,只要密码正确。

    maximumSessions:允许用户创建的最大并发HttpSession数量。

    exceptionIfMaximumExceeded:一旦并发HttpSession数量超过限额,是否抛出异常。

    Xml代码 复制代码 收藏代码
    1. <bean id="concurrentSessionController"  
    2.     class="org.acegisecurity.concurrent.ConcurrentSessionControllerImpl">  
    3.     <property name="maximumSessions" value="1"></property>  
    4.     <property name="sessionRegistry" ref="sessionRegistry"></property>  
    5.     <!--    
    6.         一般设置为false. 为true时, 如果已有一个该用户登录了, 那么在另一个地方登录该用户将抛出异常   
    7.         如果设置为false, 那么, 如果已有一个该用户登录了系统, 那么在另一个地方也可以登录, 登录后前者会被逼退出系统   
    8.     -->  
    9.     <property name="exceptionIfMaximumExceeded" value="true"></property>  
    10. </bean>  
    11.   
    12. <!--一旦认证管理器成功认证了Authentication请求,ProviderManager会立即调用concurrentSessionController验证当前用户的已登录信息。-->  
    13. <bean id="authenticationManager"  
    14.     class="org.acegisecurity.providers.ProviderManager">  
    15.     ……   
    16.     <!-- 增加 -->  
    17.     <property name="sessionController"  
    18.         ref="concurrentSessionController">  
    19.     </property>  
    20. </bean>  
    <bean id="concurrentSessionController"
    	class="org.acegisecurity.concurrent.ConcurrentSessionControllerImpl">
    	<property name="maximumSessions" value="1"></property>
    	<property name="sessionRegistry" ref="sessionRegistry"></property>
    	<!-- 
    		一般设置为false. 为true时, 如果已有一个该用户登录了, 那么在另一个地方登录该用户将抛出异常
    		如果设置为false, 那么, 如果已有一个该用户登录了系统, 那么在另一个地方也可以登录, 登录后前者会被逼退出系统
    	-->
    	<property name="exceptionIfMaximumExceeded" value="true"></property>
    </bean>
    
    <!--一旦认证管理器成功认证了Authentication请求,ProviderManager会立即调用concurrentSessionController验证当前用户的已登录信息。-->
    <bean id="authenticationManager"
    	class="org.acegisecurity.providers.ProviderManager">
    	……
    	<!-- 增加 -->
    	<property name="sessionController"
    		ref="concurrentSessionController">
    	</property>
    </bean>

     

    开发环境:

    MyEclipse 5.0GA

    Eclipse3.2.1

    JDK1.5.0_10

    tomcat5.5.23

    acegi-security-1.0.7

    Spring2.0

     

    Jar包:

    acegi-security-1.0.7.jar

    Spring.jar

    commons-codec.jar

    jstl.jar (1.1)

    standard.jar

     

     

     

     

     

    <!---->

     

    <!---->

     

     

  • 相关阅读:
    《代码大全2》阅读笔记02
    《代码大全2》阅读笔记01
    第二阶段冲刺第六天
    学习进度5
    构建之法阅读笔记03
    地铁进度记录
    学习进度4
    个人数组
    学习进度3
    构建之法阅读笔记02
  • 原文地址:https://www.cnblogs.com/wzh123/p/3392998.html
Copyright © 2020-2023  润新知