Spring Security3源码分析(14)-SessionManagementFilter分析-下

扫码关注公众号:Java 技术驿站

发送:vip
将链接复制到本浏览器,永久解锁本站全部文章

【公众号:Java 技术驿站】 【加作者微信交流技术,拉技术群】

很多spring security3资料在介绍session的并发控制都要求配置HttpSessionEventPublisher的监听器,如下

Xml代码

  1. <**listener**>
  2. <**listener-class**>
  3. org.springframework.security.web.session.HttpSessionEventPublisher
  4. </**listener-class**>
  5. </**listener**>

这个监听器实现了HttpSessionListener接口,主要监听sessionCreated、sessionDestroyed事件。看源码

Java代码

  1. public class HttpSessionEventPublisher implements HttpSessionListener {
  2. private static final Log log = LogFactory.getLog(HttpSessionEventPublisher.class);
  3. ApplicationContext getContext(ServletContext servletContext) {
  4. return WebApplicationContextUtils.getWebApplicationContext(servletContext);
  5. }
  6. public void sessionCreated(HttpSessionEvent event) {
  7. HttpSessionCreatedEvent e = new HttpSessionCreatedEvent(event.getSession());
  8. if (log.isDebugEnabled()) {
  9. log.debug(“Publishing event: “ + e);
  10. }
  11. //通过ApplicationContext的事件发布机制发布sessionCreated事件
  12. getContext(event.getSession().getServletContext()).publishEvent(e);
  13. }
  14. public void sessionDestroyed(HttpSessionEvent event) {
  15. HttpSessionDestroyedEvent e = new HttpSessionDestroyedEvent(event.getSession());
  16. if (log.isDebugEnabled()) {
  17. log.debug(“Publishing event: “ + e);
  18. }
  19. //通过ApplicationContext的事件发布机制发布sessionDestroyed事件
  20. getContext(event.getSession().getServletContext()).publishEvent(e);
  21. }
  22. }

由于ApplicationContext继承了ApplicationEventPublisher接口,所以ApplicationContext具有发布事件的能力。

Spring中与事件有关的接口和类主要包括ApplicationEvent、ApplicationListener。

定义一个事件的类需要继承ApplicationEvent或者ApplicationContextEvent抽象类。针对一种事件,需要特定的监听器,监听器需要实现ApplicationListener接口。当监听器接收到一个事件的时候,就会执行它的 onApplicationEvent()方法。

上面的代码仅仅发布了session事件,针对session事件,谁去监听并处理呢?

spring security中监听session事件的类是SessionRegistryImpl(org.springframework.security.core.session.SessionRegistryImpl)

这个类实现了ApplicationListener接口,但是这个类在哪里注册到ioc容器中的呢。

如果看完上一篇的分析,应该知道是解析标签
concurrency-control
时创建这个bean并注册到ioc容器的。如果没有配置这个标签,这个类的bean就不会产生。

接着看SessionRegistryImpl类中的处理事件的方法onApplicationEvent

Java代码

  1. //实际上SessionRegistryImpl仅仅处理SessionDestroyedEvent
  2. //接收到session失效事件,从当前缓存中清除SessionInformation
  3. public void onApplicationEvent(SessionDestroyedEvent event) {
  4. String sessionId = event.getId();
  5. removeSessionInformation(sessionId);
  6. }
  7. //根据失效的sessionid清除SessionInformation对象
  8. public void removeSessionInformation(String sessionId) {
  9. Assert.hasText(sessionId, “SessionId required as per interface contract”);
  10. SessionInformation info = getSessionInformation(sessionId);
  11. if (info == null) {
  12. return;
  13. }
  14. //从sessionIds中清除SessionInformation
  15. sessionIds.remove(sessionId);
  16. Set sessionsUsedByPrincipal = principals.get(info.getPrincipal());
  17. if (sessionsUsedByPrincipal == null) {
  18. return;
  19. }
  20. //从principals清除SessionInformation对应的认证实体信息
  21. synchronized (sessionsUsedByPrincipal) {
  22. sessionsUsedByPrincipal.remove(sessionId);
  23. if (sessionsUsedByPrincipal.size() == 0) {
  24. principals.remove(info.getPrincipal());
  25. }
  26. }
  27. }

现在,HttpSessionEventPublisher监听器的目的就很明显了。这个过滤器首先监听session失效的事件(web容器配置的timeout、直接调用session.invalidate方法),然后由SessionRegistryImpl处理session失效事件,从自己维护的集合缓存中清除已经失效的session信息以及session对应的认证实体信息,避免造成oom。

这里要重点区分下,上一篇分析的ConcurrentSessionFilter过滤器也是处理session失效,但是它所处理的仅仅封装后的SessionInformation类,如果这个类满足失效条件,再执行session.invalidate强制失效。


来源:http://ddrv.cn

赞(0) 打赏
版权归原创作者所有,任何形式的转载请联系博主:daming_90:Java 技术驿站 » Spring Security3源码分析(14)-SessionManagementFilter分析-下

评论 抢沙发

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

微信扫一扫打赏