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

相关文章

Web服务器-Nginx-高并发问题

《Web服务器-Nginx-高并发问题》Nginx通过事件驱动、I/O多路复用和异步非阻塞技术高效处理高并发,结合动静分离和限流策略,提升性能与稳定性... 目录前言一、架构1. 原生多进程架构2. 事件驱动模型3. IO多路复用4. 异步非阻塞 I/O5. Nginx高并发配置实战二、动静分离1. 职责2

Spring Security 前后端分离场景下的会话并发管理

《SpringSecurity前后端分离场景下的会话并发管理》本文介绍了在前后端分离架构下实现SpringSecurity会话并发管理的问题,传统Web开发中只需简单配置sessionManage... 目录背景分析传统 web 开发中的 sessionManagement 入口ConcurrentSess

基于Python实现数字限制在指定范围内的五种方式

《基于Python实现数字限制在指定范围内的五种方式》在编程中,数字范围限制是常见需求,无论是游戏开发中的角色属性值、金融计算中的利率调整,还是传感器数据处理中的异常值过滤,都需要将数字控制在合理范围... 目录引言一、基础条件判断法二、数学运算巧解法三、装饰器模式法四、自定义类封装法五、NumPy数组处理

Spring Security重写AuthenticationManager实现账号密码登录或者手机号码登录

《SpringSecurity重写AuthenticationManager实现账号密码登录或者手机号码登录》本文主要介绍了SpringSecurity重写AuthenticationManage... 目录一、创建自定义认证提供者CustomAuthenticationProvider二、创建认证业务Us

MySQL中处理数据的并发一致性的实现示例

《MySQL中处理数据的并发一致性的实现示例》在MySQL中处理数据的并发一致性是确保多个用户或应用程序同时访问和修改数据库时,不会导致数据冲突、数据丢失或数据不一致,MySQL通过事务和锁机制来管理... 目录一、事务(Transactions)1. 事务控制语句二、锁(Locks)1. 锁类型2. 锁粒

Springboot项目登录校验功能实现

《Springboot项目登录校验功能实现》本文介绍了Web登录校验的重要性,对比了Cookie、Session和JWT三种会话技术,分析其优缺点,并讲解了过滤器与拦截器的统一拦截方案,推荐使用JWT... 目录引言一、登录校验的基本概念二、HTTP协议的无状态性三、会话跟android踪技术1. Cook

springboot项目中集成shiro+jwt完整实例代码

《springboot项目中集成shiro+jwt完整实例代码》本文详细介绍如何在项目中集成Shiro和JWT,实现用户登录校验、token携带及接口权限管理,涉及自定义Realm、ModularRe... 目录简介目的需要的jar集成过程1.配置shiro2.创建自定义Realm2.1 LoginReal

SpringBoot集成Shiro+JWT(Hutool)完整代码示例

《SpringBoot集成Shiro+JWT(Hutool)完整代码示例》ApacheShiro是一个强大且易用的Java安全框架,提供了认证、授权、加密和会话管理功能,在现代应用开发中,Shiro因... 目录一、背景介绍1.1 为什么使用Shiro?1.2 为什么需要双Token?二、技术栈组成三、环境

深入解析Java NIO在高并发场景下的性能优化实践指南

《深入解析JavaNIO在高并发场景下的性能优化实践指南》随着互联网业务不断演进,对高并发、低延时网络服务的需求日益增长,本文将深入解析JavaNIO在高并发场景下的性能优化方法,希望对大家有所帮助... 目录简介一、技术背景与应用场景二、核心原理深入分析2.1 Selector多路复用2.2 Buffer

使用Redis快速实现共享Session登录的详细步骤

《使用Redis快速实现共享Session登录的详细步骤》在Web开发中,Session通常用于存储用户的会话信息,允许用户在多个页面之间保持登录状态,Redis是一个开源的高性能键值数据库,广泛用于... 目录前言实现原理:步骤:使用Redis实现共享Session登录1. 引入Redis依赖2. 配置R