基于java config的springSecurity(五)--session并发控制
来源:互联网 发布:金融大数据语言 编辑:程序博客网 时间:2024/06/02 04:51
参考资料:spring-security-reference.pdf的Session Management.特别是Concurrency Control小节.
管理session可以做到:
a.跟踪活跃的session,统计在线人数,显示在线用户.
b.控制并发,即一个用户最多可以使用多少个session登录,比如设为1,结果就为,同一个时间里,第二处登录要么不能登录,要么使前一个登录失效.
1.注册自定义的SessionRegistry(通过它可以做到上面的a点)
2.使用session并发管理,并注入上面自定义的SessionRegistry3.监听session创建和销毁的HttpSessionListener.让spring security更新有关会话的生命周期,实现上创建的监听只使用销毁事件,至于session创建,security是调用org.springframework.security.core.session.SessionRegistry#registerNewSession
针对servlet管理的session,应使用org.springframework.security.web.session.HttpSessionEventPublisher,方法有多种:
a.重写org.springframework.security.web.context.AbstractSecurityWebApplicationInitializer#enableHttpSessionEventPublisher
b.在AbstractAnnotationConfigDispatcherServletInitializer的子类DispatcherServletInitializer添加
使用springSession,直接向servletContext添加的session销毁监听是没用的,看springSession的文档http://docs.spring.io/spring-session/docs/current/reference/html5/#httpsession-httpsessionlistener,将org.springframework.security.web.session.HttpSessionEventPublisher注册成Bean就可以了.它的底层是对springSession的创建和销毁进行监听,不一样的.还要注意的是,添加对HttpSessionListener的支持是从spring Session 1.1.0开始的,写这博文的时候,这版本还没出来.所以,以前的源码有问题.
4.在spring controller注入SessionRegistry,测试.附加session的创建与销毁分析:至于session的创建比较简单,认证成功后,security直接调用
session的销毁.没有特殊修改,org.springframework.security.web.authentication.logout.LogoutFilter#handlers只有一个元素org.springframework.security.web.authentication.logout.SecurityContextLogoutHandler,如果主动logout,就会触发org.springframework.security.web.authentication.logout.LogoutFilter#doFilter,进而调用org.springframework.security.web.authentication.logout.SecurityContextLogoutHandler#logout,从这个方法可以看出别人是怎么处理失效的session的
这里可以看到使session失效,调用SecurityContextHolder.getContext().setAuthentication(null),清理SecurityContextspring security登出操作和session过期都会引起session被销毁.就会触发org.springframework.security.web.session.HttpSessionEventPublisher#sessionDestroyed事件.源码如下
getContext(event.getSession().getServletContext())得到的是Root ApplicationContext,所以要把SessionRegistryImpl Bean注册到Root ApplicationContext,这样SessionRegistryImpl的onApplicationEvent方法才能接收上面发布的HttpSessionDestroyedEvent事件.
这里就看removeSessionInformation(sessionId);这里就会对SessionRegistryImpl相关信息进会更新.进而通过SessionRegistryImpl获得那些用户登录了,一个用户有多少个SessionInformation都进行了同步.再来讨论getContext(event.getSession().getServletContext())
再假设得到的Servlet ApplicationContext,它还有parent(Root ApplicationContext),那么它也会通知Root ApplicationContext下监听SessionDestroyedEvent事件的Bean,(哈哈,但是没有那么多的如果);但我还要如果用户就想在servlet注册SessionRegistryImpl,我觉得你可以继承HttpSessionEventPublisher,重写getContext方法了针对于servlet容器的session,至于session过期,如果想测试,可以去改一下session的有效期短一点,然后等待观察.下面是我的测试web.xml全部内容
对于用户主动关闭浏览器,服务端是没有马上触发sessionDestroyed的,等待session过期应该是大多数开发者的需求.关于踢下线功能:使用org.springframework.security.core.session.SessionRegistry#getAllSessions就可以得到某个用户的所有SessionInformation,SessionInformation当然包括sessionId,剩下的问题就是根据sessionId获取session,再调用session.invalidate()就可以完成需求了.但是javax.servlet.http.HttpSessionContext#getSession已过期,并且因为安全原因没有替代方案,所以从servlet api2.1以后的版本,此路是不通的.spring security提供了org.springframework.security.core.session.SessionInformation#expireNow,它只是标志了一下过期,直到下次用户请求被org.springframework.security.web.session.ConcurrentSessionFilter#doFilter拦截,
这里就会触发了用户登出.还有一种思路,session保存在redis,直接从redis删除某个session数据,详细看org.springframework.session.SessionRepository,不太推荐这么干.还有SessionRegistryImpl实现的并发控制靠以下两个变量实现的用户在线列表,重启应用这两个实例肯定会销毁,/** <principal:Object,SessionIdSet> */private final ConcurrentMap<Object, Set<String>> principals = new ConcurrentHashMap<Object, Set<String>>();/** <sessionId:Object,SessionInformation> */private final Map<String, SessionInformation> sessionIds = new ConcurrentHashMap<String, SessionInformation>();既然分布式应用也会有问题,这时就要实现自己的SessionRegistry,将session的信息应保存到一个集中的地方进行管理.
阅读全文
0 0
- 基于java config的springSecurity(五)--session并发控制
- 基于java config的springSecurity(五)--session并发控制
- 基于java config的springSecurity(六)--集成spring session
- 基于java config的springSecurity(六)--集成spring session
- 基于java config的springSecurity--单元测试
- 基于java config的springSecurity--单元测试
- 基于java config的springSecurity(一)--基本搭建
- 基于java config的springSecurity(二)--自定义认证
- 基于java config的springSecurity(四)--启用全局方法安全
- 基于java config的springSecurity(一)--基本搭建
- 基于java config的springSecurity(二)--自定义认证
- 基于java config的springSecurity(四)--启用全局方法安全
- 基于java config的springSecurity(二)--自定义认证
- 基于java config的springSecurity(三)--加入RememberMe,启用CSRF和增强密码
- 基于java config的springSecurity(三)--加入RememberMe,启用CSRF和增强密码
- 五篇基于java config的spring security
- Spring in Action(五):基于Java Config的SpringMVC
- 基于rest的SpringSecurity(基于认证)
- Kotlin踩坑笔记
- 怎样给linux 7 安装阿里云的yum源?
- Xshell连接虚拟机linux操作系统
- Python环境搭建之OpenCV
- UE4 代码总结
- 基于java config的springSecurity(五)--session并发控制
- studio Terminal命令
- 夜神模拟器连接不上Android Studio
- Smali插入后重新打包签名
- Cannot start container web: iptables failed: iptables -t nat -A DOCKER -p tcp -d 0/0 --dport 32797
- css伪类和伪元素的区别
- quartz 多线程 线程池
- Linux搭建Java服务器环境-Tomcat安装
- 关于Direct2D