Shiro - 限制并发人数登录与剔除

2024-04-17 06:38

本文主要是介绍Shiro - 限制并发人数登录与剔除,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

原文地址:https://www.cnblogs.com/leechenxiang/p/6171151.html

  1. import org.apache.shiro.cache.Cache;
  2. import org.apache.shiro.cache.CacheManager;
  3. import org.apache.shiro.session.Session;
  4. import org.apache.shiro.session.mgt.DefaultSessionKey;
  5. import org.apache.shiro.session.mgt.SessionManager;
  6. import org.apache.shiro.subject.Subject;
  7. import org.apache.shiro.web.filter.AccessControlFilter;
  8. import org.apache.shiro.web.util.WebUtils;
  9. import com.agood.pojo.ActiveUser;
  10. import javax.servlet.ServletRequest;
  11. import javax.servlet.ServletResponse;
  12. import javax.servlet.http.HttpServletRequest;
  13. import javax.servlet.http.HttpServletResponse;
  14. import java.io.Serializable;
  15. import java.util.Deque;
  16. import java.util.LinkedList;
  17. /**
  18. *
  19. * @Title: KickoutSessionControlFilter.java
  20. * @Package com.agood.bejavagod.controller.filter
  21. * @Description: 同一用户后登陆踢出前面的用户
  22. * Copyright: Copyright (c) 2016
  23. * Company:Nathan.Lee.Salvatore
  24. *
  25. * @author leechenxiang
  26. * @date 2016年12月12日 下午7:25:40
  27. * @version V1.0
  28. */
  29. public class KickoutSessionControlFilter extends AccessControlFilter {
  30. private String kickoutUrl; //踢出后到的地址
  31. private boolean kickoutAfter = false; //踢出之前登录的/之后登录的用户 默认踢出之前登录的用户
  32. private int maxSession = 1; //同一个帐号最大会话数 默认1
  33. private SessionManager sessionManager;
  34. private Cache<String, Deque<Serializable>> cache;
  35. public void setKickoutUrl(String kickoutUrl) {
  36. this.kickoutUrl = kickoutUrl;
  37. }
  38. public void setKickoutAfter(boolean kickoutAfter) {
  39. this.kickoutAfter = kickoutAfter;
  40. }
  41. public void setMaxSession(int maxSession) {
  42. this.maxSession = maxSession;
  43. }
  44. public void setSessionManager(SessionManager sessionManager) {
  45. this.sessionManager = sessionManager;
  46. }
  47. public void setCacheManager(CacheManager cacheManager) {
  48. this.cache = cacheManager.getCache("shiro-kickout-session");
  49. }
  50. @Override
  51. protected boolean isAccessAllowed(ServletRequest request, ServletResponse response, Object mappedValue) throws Exception {
  52. return false;
  53. }
  54. @Override
  55. protected boolean onAccessDenied(ServletRequest request, ServletResponse response) throws Exception {
  56. Subject subject = getSubject(request, response);
  57. if(!subject.isAuthenticated() && !subject.isRemembered()) {
  58. //如果没有登录,直接进行之后的流程
  59. return true;
  60. }
  61. Session session = subject.getSession();
  62. ActiveUser user = (ActiveUser)subject.getPrincipal();
  63. String username = user.getUserName();
  64. Serializable sessionId = session.getId();
  65. // 同步控制
  66. Deque<Serializable> deque = cache.get(username);
  67. if(deque == null) {
  68. deque = new LinkedList<Serializable>();
  69. cache.put(username, deque);
  70. }
  71. //如果队列里没有此sessionId,且用户没有被踢出;放入队列
  72. if(!deque.contains(sessionId) && session.getAttribute("kickout") == null) {
  73. deque.push(sessionId);
  74. }
  75. //如果队列里的sessionId数超出最大会话数,开始踢人
  76. while(deque.size() > maxSession) {
  77. Serializable kickoutSessionId = null;
  78. if(kickoutAfter) { //如果踢出后者
  79. kickoutSessionId = deque.removeFirst();
  80. } else { //否则踢出前者
  81. kickoutSessionId = deque.removeLast();
  82. }
  83. try {
  84. Session kickoutSession = sessionManager.getSession(new DefaultSessionKey(kickoutSessionId));
  85. if(kickoutSession != null) {
  86. //设置会话的kickout属性表示踢出了
  87. kickoutSession.setAttribute("kickout", true);
  88. }
  89. } catch (Exception e) {//ignore exception
  90. }
  91. }
  92. //如果被踢出了,直接退出,重定向到踢出后的地址
  93. if (session.getAttribute("kickout") != null) {
  94. //会话被踢出了
  95. try {
  96. subject.logout();
  97. } catch (Exception e) { //ignore
  98. }
  99. saveRequest(request);
  100. HttpServletRequest httpRequest = WebUtils.toHttp(request);
  101. if (ShiroFilterUtils.isAjax(httpRequest)) {
  102. HttpServletResponse httpServletResponse = WebUtils.toHttp(response);
  103. httpServletResponse.sendError(ShiroFilterUtils.HTTP_STATUS_SESSION_EXPIRE);
  104. return false;
  105. } else {
  106. WebUtils.issueRedirect(request, response, kickoutUrl);
  107. return false;
  108. }
  109. }
  110. return true;
  111. }
  112. }

首先得要有个过滤器命名为:KickoutSessionControlFilter

然后在shiro.xml中需要这么定义:


  1. <property name="filters">
  2. <map>
  3. <entry key="kickout" value-ref="kickoutSessionControlFilter"/>
  4. </map>
  5. </property>

  1. <bean id="kickoutSessionControlFilter" class="com.agood.bejavagod.controller.filter.KickoutSessionControlFilter">
  2. <property name="cacheManager" ref="shiroEhcacheManager"/>
  3. <property name="sessionManager" ref="sessionManager"/>
  4. <!-- 是否踢出后来登录的,默认是false;即后者登录的用户踢出前者登录的用户 -->
  5. <property name="kickoutAfter" value="false"/>
  6. <!-- 同一个用户最大的会话数,默认1;比如2的意思是同一个用户允许最多同时两个人登录 -->
  7. <property name="maxSession" value="1"/>
  8. <property name="kickoutUrl" value="/login.action"/>
  9. </bean>
最后修改过滤器配置,拦截所有请求

/** = kickout,authc



这篇关于Shiro - 限制并发人数登录与剔除的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/911060

相关文章

全面解析MySQL索引长度限制问题与解决方案

《全面解析MySQL索引长度限制问题与解决方案》MySQL对索引长度设限是为了保持高效的数据检索性能,这个限制不是MySQL的缺陷,而是数据库设计中的权衡结果,下面我们就来看看如何解决这一问题吧... 目录引言:为什么会有索引键长度问题?一、问题根源深度解析mysql索引长度限制原理实际场景示例二、五大解决

CSS3打造的现代交互式登录界面详细实现过程

《CSS3打造的现代交互式登录界面详细实现过程》本文介绍CSS3和jQuery在登录界面设计中的应用,涵盖动画、选择器、自定义字体及盒模型技术,提升界面美观与交互性,同时优化性能和可访问性,感兴趣的朋... 目录1. css3用户登录界面设计概述1.1 用户界面设计的重要性1.2 CSS3的新特性与优势1.

Java中的登录技术保姆级详细教程

《Java中的登录技术保姆级详细教程》:本文主要介绍Java中登录技术保姆级详细教程的相关资料,在Java中我们可以使用各种技术和框架来实现这些功能,文中通过代码介绍的非常详细,需要的朋友可以参考... 目录1.登录思路2.登录标记1.会话技术2.会话跟踪1.Cookie技术2.Session技术3.令牌技

python多线程并发测试过程

《python多线程并发测试过程》:本文主要介绍python多线程并发测试过程,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录一、并发与并行?二、同步与异步的概念?三、线程与进程的区别?需求1:多线程执行不同任务需求2:多线程执行相同任务总结一、并发与并行?1、

Nginx 413修改上传文件大小限制的方法详解

《Nginx413修改上传文件大小限制的方法详解》在使用Nginx作为Web服务器时,有时会遇到客户端尝试上传大文件时返回​​413RequestEntityTooLarge​​... 目录1. 理解 ​​413 Request Entity Too Large​​ 错误2. 修改 Nginx 配置2.1

SpringBoot后端实现小程序微信登录功能实现

《SpringBoot后端实现小程序微信登录功能实现》微信小程序登录是开发者通过微信提供的身份验证机制,获取用户唯一标识(openid)和会话密钥(session_key)的过程,这篇文章给大家介绍S... 目录SpringBoot实现微信小程序登录简介SpringBoot后端实现微信登录SpringBoo

Linux高并发场景下的网络参数调优实战指南

《Linux高并发场景下的网络参数调优实战指南》在高并发网络服务场景中,Linux内核的默认网络参数往往无法满足需求,导致性能瓶颈、连接超时甚至服务崩溃,本文基于真实案例分析,从参数解读、问题诊断到优... 目录一、问题背景:当并发连接遇上性能瓶颈1.1 案例环境1.2 初始参数分析二、深度诊断:连接状态与

Windows系统宽带限制如何解除?

《Windows系统宽带限制如何解除?》有不少用户反映电脑网速慢得情况,可能是宽带速度被限制的原因,只需解除限制即可,具体该如何操作呢?本文就跟大家一起来看看Windows系统解除网络限制的操作方法吧... 有不少用户反映电脑网速慢得情况,可能是宽带速度被限制的原因,只需解除限制即可,具体该如何操作呢?本文

Java并发编程之如何优雅关闭钩子Shutdown Hook

《Java并发编程之如何优雅关闭钩子ShutdownHook》这篇文章主要为大家详细介绍了Java如何实现优雅关闭钩子ShutdownHook,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起... 目录关闭钩子简介关闭钩子应用场景数据库连接实战演示使用关闭钩子的注意事项开源框架中的关闭钩子机制1.

kali linux 无法登录root的问题及解决方法

《kalilinux无法登录root的问题及解决方法》:本文主要介绍kalilinux无法登录root的问题及解决方法,本文给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,... 目录kali linux 无法登录root1、问题描述1.1、本地登录root1.2、ssh远程登录root2、