shiro并发人数登录控制的实现代码

在某些项目中可能会遇到如每个账户同时只能有一个人登录或几个人同时登录,如果同时有多人登录:要么不让后者登录;要么踢出前者登录(强制退出)。比如spring security就直接提供了相应的功能;Shiro的话没有提供默认实现,不过可以很容易的在Shiro中加入这个功能。

通过Shiro Filter机制扩展KickoutSessionControlFilter完成。

首先来看看如何配置使用(spring-config-shiro.xml)  

kickoutSessionControlFilter用于控制并发登录人数的

Java代码

<bean id="kickoutSessionControlFilter"
class="com.github.zhangkaitao.shiro.chapter18.web.shiro.filter.KickoutSessionControlFilter">
 <property name="cacheManager" ref="cacheManager"/>
 <property name="sessionManager" ref="sessionManager"/>
 <property name="kickoutAfter" value="false"/>
 <property name="maxSession" value="2"/>
 <property name="kickoutUrl" value="/login?kickout=1"/>
</bean> 

cacheManager:使用cacheManager获取相应的cache来缓存用户登录的会话;用于保存用户—会话之间的关系的;

sessionManager:用于根据会话ID,获取会话进行踢出操作的;

kickoutAfter:是否踢出后来登录的,默认是false;即后者登录的用户踢出前者登录的用户;

maxSession:同一个用户最大的会话数,默认1;比如2的意思是同一个用户允许最多同时两个人登录;

kickoutUrl:被踢出后重定向到的地址;

shiroFilter配置 

Java代码

<bean id="shiroFilter" class="org.apache.shiro.spring.web.ShiroFilterFactoryBean">
 <property name="securityManager" ref="securityManager"/>
 <property name="loginUrl" value="/login"/>
 <property name="filters">
  <util:map>
  <entry key="authc" value-ref="formAuthenticationFilter"/>
  <entry key="sysUser" value-ref="sysUserFilter"/>
  <entry key="kickout" value-ref="kickoutSessionControlFilter"/>
  </util:map>
 </property>
 <property name="filterChainDefinitions">
  <value>
  /login = authc
  /logout = logout
  /authenticated = authc
  /** = kickout,user,sysUser
  </value>
 </property>
 </bean> 

此处配置除了登录等之外的地址都走kickout拦截器进行并发登录控制。

测试

此处因为maxSession=2,所以需要打开3个浏览器(需要不同的浏览器,如IE、Chrome、Firefox),分别访问http://localhost:8080/chapter18/进行登录;然后刷新第一次打开的浏览器,将会被强制退出,如显示下图:

KickoutSessionControlFilter核心代码: 

Java代码

protected boolean onAccessDenied(ServletRequest request, ServletResponse response) throws Exception {
 Subject subject = getSubject(request, response);
 if(!subject.isAuthenticated() && !subject.isRemembered()) {
 //如果没有登录,直接进行之后的流程
 return true;
 }
 Session session = subject.getSession();
 String username = (String) subject.getPrincipal();
 Serializable sessionId = session.getId();
 //TODO 同步控制
 Deque<Serializable> deque = cache.get(username);
 if(deque == null) {
 deque = new LinkedList<Serializable>();
 cache.put(username, deque);
 }
 //如果队列里没有此sessionId,且用户没有被踢出;放入队列
 if(!deque.contains(sessionId) && session.getAttribute("kickout") == null) {
 deque.push(sessionId);
 }
 //如果队列里的sessionId数超出最大会话数,开始踢人
 while(deque.size() > maxSession) {
 Serializable kickoutSessionId = null;
 if(kickoutAfter) { //如果踢出后者
  kickoutSessionId = deque.removeFirst();
 } else { //否则踢出前者
  kickoutSessionId = deque.removeLast();
 }
 try {
  Session kickoutSession =
  sessionManager.getSession(new DefaultSessionKey(kickoutSessionId));
  if(kickoutSession != null) {
  //设置会话的kickout属性表示踢出了
  kickoutSession.setAttribute("kickout", true);
  }
 } catch (Exception e) {//ignore exception
 }
 }
 //如果被踢出了,直接退出,重定向到踢出后的地址
 if (session.getAttribute("kickout") != null) {
 //会话被踢出了
 try {
  subject.logout();
 } catch (Exception e) { //ignore
 }
 saveRequest(request);
 WebUtils.issueRedirect(request, response, kickoutUrl);
 return false;
 }
 return true;
} 

此处使用了Cache缓存用户名—会话id之间的关系;如果量比较大可以考虑如持久化到数据库/其他带持久化的Cache中;另外此处没有并发控制的同步实现,可以考虑根据用户名获取锁来控制,减少锁的粒度。

总结

以上所述是小编给大家介绍的shiro并发人数登录控制的实现代码,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对我们网站的支持!

(0)

相关推荐

  • Shiro 控制并发登录人数限制及登录踢出的实现代码

    我们经常会有用到,当A 用户在北京登录 ,然后A用户在天津再登录 ,要踢出北京登录的状态.如果用户在北京重新登录,那么又要踢出天津的用户,这样反复. 这样保证了一个帐号只能同时一个人使用.那么下面来讲解一下 Shiro  怎么实现这个功能,现在是用到了缓存 Redis  .我们也可以用其他缓存.如果是单个点,直接用一个静态的Map<String,Object> 或者 Ehcache  即可. XML配置. <!-- session 校验单个用户是否多次登录 --> <bean

  • SpringBoot+Shiro学习之密码加密和登录失败次数限制示例

    这个项目写到现在,基本的雏形出来了,在此感谢一直关注的童鞋,送你们一句最近刚学习的一句鸡汤:念念不忘,必有回响.再贴一张ui图片: 前篇思考问题解决 前篇我们只是完成了同一账户的登录人数限制shiro拦截器的编写,对于手动踢出用户的功能只是说了采用在session域中添加一个key为kickout的布尔值,由之前编写的KickoutSessionControlFilter拦截器来判断是否将用户踢出,还没有说怎么获取当前在线用户的列表的核心代码,下面贴出来: /** * <p> * 服务实现类

  • 使用Shiro实现登录成功后跳转到之前的页面

    这个问题是之前在做登录注册模块时遇到的需求,如何用户直接访问登录页面,可以控制直接跳到首页,但是如果是用户没有登录直接访问了购物车等需要经过身份认证的页面,或者是因为session超时,用户需要重新登录,那么这时跳回之前的页面就是提升用户体验的事情.实现此功能比较好的方法是用ajax的方式登陆,这样直接在当前页面弹窗让用户登录既可,二是把用户未登录前的url存在session中,login成功之后先检查session中是否存在这样的一个url.下面通过一段代码给大家分享下: 项目中集成了shir

  • Java中SSM+Shiro系统登录验证码的实现方法

     先给大家展示下效果图: 1.验证码生成类: import java.util.Random; import java.awt.image.BufferedImage; import java.awt.Graphics; import java.awt.Font; import java.awt.Color; /** * 验证码生成器类,可生成数字.大写.小写字母及三者混合类型的验证码. 支持自定义验证码字符数量: 支持自定义验证码图片的大小: 支持自定义需排除的特殊字符: * 支持自定义干扰线

  • shiro实现单点登录(一个用户同一时刻只能在一个地方登录)

    我这里 shiro 并没有集成 springMVC,直接使用 ini 配置文件. shiro.ini [main] # Objects and their properties are defined here, # Such as the securityManager, Realms and anything # else needed to build the SecurityManager authc.loginUrl = /login.jsp authc.successUrl = /w

  • springmvc集成shiro登录权限示例代码

    一般的登录流程会有:用户名不存在,密码错误,验证码错误等.. 在集成shiro后,应用程序的外部访问权限以及访问控制交给了shiro来管理. shiro提供了两个主要功能:认证(Authentication)和授权(Authorization);认证的作用是证明自身可以访问,一般是用户名加密码,授权的作用是谁可以访问哪些资源,通过开发者自己的用户角色权限系统来控制. shiro的会话管理和缓存管理不在本文范围内. 下面通过登录失败的处理流程来介绍springmvc与shiro的集成. 项目依赖:

  • shiro并发人数登录控制的实现代码

    在某些项目中可能会遇到如每个账户同时只能有一个人登录或几个人同时登录,如果同时有多人登录:要么不让后者登录:要么踢出前者登录(强制退出).比如spring security就直接提供了相应的功能:Shiro的话没有提供默认实现,不过可以很容易的在Shiro中加入这个功能. 通过Shiro Filter机制扩展KickoutSessionControlFilter完成. 首先来看看如何配置使用(spring-config-shiro.xml)   kickoutSessionControlFilt

  • spring boot整合Shiro实现单点登录的示例代码

    Shiro是什么 Shiro是一个Java平台的开源权限框架,用于认证和访问授权.具体来说,满足对如下元素的支持: 用户,角色,权限(仅仅是操作权限,数据权限必须与业务需求紧密结合),资源(url). 用户分配角色,角色定义权限. 访问授权时支持角色或者权限,并且支持多级的权限定义. Q:对组的支持? A:shiro默认不支持对组设置权限. Q:是否可以满足对组进行角色分配的需求? A:扩展Realm,可以支持对组进行分配角色,其实就是给该组下的所有用户分配权限. Q:对数据权限的支持? 在业务

  • Springboot+Vue+shiro实现前后端分离、权限控制的示例代码

    本文总结自实习中对项目的重构.原先项目采用Springboot+freemarker模版,开发过程中觉得前端逻辑写的实在恶心,后端Controller层还必须返回Freemarker模版的ModelAndView,逐渐有了前后端分离的想法,由于之前,没有接触过,主要参考的还是网上的一些博客教程等,初步完成了前后端分离,在此记录以备查阅. 一.前后端分离思想 前端从后端剥离,形成一个前端工程,前端只利用Json来和后端进行交互,后端不返回页面,只返回Json数据.前后端之间完全通过public A

  • shiro多验证登录代码实例及问题解决

    这篇文章主要介绍了shiro多验证登录代码实例及问题解决,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 1. 首先新建一个shiroConfig shiro的配置类,代码如下: @Configuration是标识这个类是一个配置文件,在启动时会加载这个类里面的内容,这个配置文件的位置的一定一定一定不能防止启动类外面的文件夹中,否则还会在启动类上加注解 @Bean是将这个类交给spring管理 @Configuration public clas

  • Springboot+Shiro记录用户登录信息并获取当前登录用户信息的实现代码

    由于最近做项目需要,在用户登陆后有一个功能是需要用户的信息,进行写入数据库的操作.但是目前还用不到Shiro的高级权限,只为了简单获取用户信息,自己整合了一个只记录用户,获取用户信息的功能. 导入Shiro依赖 <!-- Shiro --> <dependency> <groupId>org.apache.shiro</groupId> <artifactId>shiro-spring</artifactId> <version

  • JavaScript/TypeScript 实现并发请求控制的示例代码

    场景 假设有 10 个请求,但是最大的并发数目是 5 个,并且要求拿到请求结果,这样就是一个简单的并发请求控制 模拟 利用 setTimeout 实行简单模仿一个请求 let startTime = Date.now(); const timeout = (timeout: number, ret: number) => { return (idx?: any) => new Promise((resolve) => { setTimeout(() => { const compa

  • Springboot+Spring Security实现前后端分离登录认证及权限控制的示例代码

    目录 前言 本文主要的功能 一.准备工作 1.统一错误码枚举 2.统一json返回体 3.返回体构造工具 4.pom 5.配置文件 二.数据库表设计 初始化表数据语句 三.Spring Security核心配置:WebSecurityConfig 四.用户登录认证逻辑:UserDetailsService 1.创建自定义UserDetailsService 2.准备service和dao层方法 五.用户密码加密 六.屏蔽Spring Security默认重定向登录页面以实现前后端分离功能 1.实

  • Spring Security实现统一登录与权限控制的示例代码

    目录 项目介绍 统一认证中心 配置授权服务器 配置WebSecurity 登录 菜单 鉴权 资源访问的一些配置 有用的文档 项目介绍 最开始是一个单体应用,所有功能模块都写在一个项目里,后来觉得项目越来越大,于是决定把一些功能拆分出去,形成一个一个独立的微服务,于是就有个问题了,登录.退出.权限控制这些东西怎么办呢?总不能每个服务都复制一套吧,最好的方式是将认证与鉴权也单独抽离出来作为公共的服务,业务系统只专心做业务接口开发即可,完全不用理会权限这些与之不相关的东西了.于是,便有了下面的架构图:

  • Spring Security 自动踢掉前一个登录用户的实现代码

    登录成功后,自动踢掉前一个登录用户,松哥第一次见到这个功能,就是在扣扣里边见到的,当时觉得挺好玩的. 自己做开发后,也遇到过一模一样的需求,正好最近的 Spring Security 系列正在连载,就结合 Spring Security 来和大家聊一聊这个功能如何实现. 本文是本系列的第十三篇,阅读前面文章有助于更好的理解本文: 挖一个大坑,Spring Security 开搞! 松哥手把手带你入门 Spring Security,别再问密码怎么解密了 手把手教你定制 Spring Securi

  • springmvc+shiro+maven 实现登录认证与权限授权管理

    Shiro 是Shiro 是一个 Apache 下的一开源项目项目,旨在简化身份验证和授权. 1:shiro的配置,通过maven加入shiro相关jar包 <!-- shiro --> <dependency> <groupId>org.apache.shiro</groupId> <artifactId>shiro-core</artifactId> <version>1.2.1</version> <

随机推荐