今天就讲个ConcurrentSessionFilter。

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

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

1、将concurrentSessionFilter添加到filterChainProxy中

  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暴露了sessionRegistry和expiredUrl属性,sessionRegistry引用一个HttpSession注册器,这一注册器动态维护了登录到这一Web应用的所有HttpSession信息。

ConcurrentSessionFilter起到两个作用:

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

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

  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的实现类是SessionRegistryImpl,SessionRegistryImpl实现了ApplicationListener,而且它会负责应对HttpSessionDestroyedEvent事件。一旦SessionRegistryImpl接收到HttpSessionDestroyedEvent事件,则它会把触发这一事件的HttpSession的相关信息从当前注册器中清除掉。因此,HttpSessionEventPublisher的配置工作显得格外重要。在web.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数量超过限额,是否抛出异常。

  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. <!--一旦认证管理器成功认证了Authentication请求,ProviderManager会立即调用concurrentSessionController验证当前用户的已登录信息。-->
  12. <bean id="authenticationManager"
  13. class="org.acegisecurity.providers.ProviderManager">
  14. ……
  15. <!-- 增加 -->
  16. <property name="sessionController"
  17. ref="concurrentSessionController">
  18. </property>
  19. </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

<!---->

<!---->

菜鸟-手把手教你把Acegi应用到实际项目中(4)的更多相关文章

  1. 菜鸟-手把手教你把Acegi应用到实际项目中(8)-扩展UserDetailsService接口

    一个能为DaoAuthenticationProvider提供存取认证库的的类,它必须要实现UserDetailsService接口: public UserDetails loadUserByUse ...

  2. 菜鸟-手把手教你把Acegi应用到实际项目中(10)-保护业务方法

    前面已经讲过关于保护Web资源的方式,其中包括直接在XML文件中配置和自定义实现FilterInvocationDefinitionSource接口两种方式.在实际企业应用中,保护Web资源显得非常重 ...

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

    相信不少朋友们对于学习Acegi的过程是比较痛苦的,而且可能最初一个例子都没能真正运行起来.即使能运行起来,对于里面那么多的配置,更搞不清楚为什么要那么配,多配一个和少配一个究竟有什么区别? 最终头都 ...

  4. 菜鸟-手把手教你把Acegi应用到实际项目中(11)-切换用户

    在某些应用场合中,我们可能需要用到切换用户的功能,从而以另一用户的身份进行相关操作.这一点类似于在Linux系统中,用su命令切换到另一用户进行相关操作.      既然实际应用中有这种场合,那么我们 ...

  5. 菜鸟-手把手教你把Acegi应用到实际项目中(12)-Run-As认证服务

    有这样一些场合,系统用户必须以其他角色身份去操作某些资源.例如,用户A要访问资源B,而用户A拥有的角色为AUTH_USER,资源B访问的角色必须为AUTH_RUN_AS_DATE,那么此时就必须使用户 ...

  6. 菜鸟-手把手教你把Acegi应用到实际项目中(7)-缓存用户信息

    首先讲讲EhCache.在默认情况下,即在用户未提供自身配置文件ehcache.xml或ehcache-failsafe.xml时,EhCache会依据其自身Jar存档包含的ehcache-fails ...

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

    在实际企业应用中,用户密码一般都会进行加密处理,这样才能使企业应用更加安全.既然密码的加密如此之重要,那么Acegi(Spring Security)作为成熟的安全框架,当然也我们提供了相应的处理方式 ...

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

    在企业应用中,用户的用户名.密码和角色等信息一般存放在RDBMS(关系数据库)中.前面几节我们采用的是InMemoryDaoImpl,即基于内存的存放方式.这节我们将采用RDBMS存储用户信息. Us ...

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

    7) daoAuthenticationProvider 进行简单的基于数据库的身份验证.DaoAuthenticationProvider获取数据库中的账号密码并进行匹配,若成功则在通过用户身份的同 ...

随机推荐

  1. C# Color Table颜色对照表

    .AliceBlue 240,248,255 .LightSalmon 255,160,122 .AntiqueWhite 250,235,215 .LightSeaGreen 32,178,170 ...

  2. 【性能测试】性能测试总结<四>

    性能测试常见指标        性能测试说白了就是通过工具模拟多个用户对被测系统进行访问.然后查看系统对于多个用户发来请求的处理能力. 左边的两个小人表示两个用户,向右边服务器发送请求,然后得到服务器 ...

  3. 【linux】man和--help

    man和--help都是获取命令帮助的指令. man 格式: man [命令] [root@andon tmp]# man pwd --help 命令 --help [root@andon tmp]# ...

  4. 解决方案:将已存在的项目 添加到 tfs解决方案中的时候 出现:新项目不能成功加入源码控制

    遇到此问题 可能是因为你的 解决方案文件 没有正确与 tfs服务器绑定导致的 解决方式是: 在打开任意一个源码文件的时候,打开 vs2013的 文件>> Go to File->So ...

  5. 剑指offer系列54---数组中出现次数超过一半的数

    [题目]数组中有一个数字出现的次数超过数组长度的一半,请找出这个数字. * 例如输入一个长度为9的数组{1,2,3,2,2,2,5,4,2}. * 由于数字2在数组中出现了5次,超过数组长度的一半,因 ...

  6. html body标签的几个属性 禁用鼠标右键,禁用鼠标选中文字等

    <body oncontextmenu='return false' ondragstart='return false' onselectstart ='return false' onsel ...

  7. poj1160 post office

    题目大意:有n个乡村,现在要建立m个邮局,邮局只能建在乡村里.现在要使每个乡村到离它最近的邮局距离的总和尽量小,求这个最小距离和. n<300,p<30,乡村的位置不超过10000. 分析 ...

  8. free命令、buffer与cache的区别

    freefree 命令相对于top 提供了更简洁的查看系统内存使用情况: # free total used free shared buffers cached Mem: 255988 231704 ...

  9. activiti自定义流程之自定义表单(一):环境配置

    先补充说一下自定义流程整个的思路,自定义流程的目的就是为了让一套代码解决多种业务流程,比如请假单.报销单.采购单.协作单等等,用户自己来设计流程图. 这里要涉及到这样几个基本问题,一是不同的业务需求, ...

  10. AP_应付税务预扣税Withholding Tax中付款时产生预扣税(案例)

    2014-07-12 Created By BaoXinjian