Shiro - 限制并发人数登录与剔除
import org.apache.shiro.cache.Cache;
import org.apache.shiro.cache.CacheManager;
import org.apache.shiro.session.Session;
import org.apache.shiro.session.mgt.DefaultSessionKey;
import org.apache.shiro.session.mgt.SessionManager;
import org.apache.shiro.subject.Subject;
import org.apache.shiro.web.filter.AccessControlFilter;
import org.apache.shiro.web.util.WebUtils; import com.agood.pojo.ActiveUser; import javax.servlet.ServletRequest;
import javax.servlet.ServletResponse;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse; import java.io.Serializable;
import java.util.Deque;
import java.util.LinkedList; /**
*
* @Title: KickoutSessionControlFilter.java
* @Package com.agood.bejavagod.controller.filter
* @Description: 同一用户后登陆踢出前面的用户
* Copyright: Copyright (c) 2016
* Company:Nathan.Lee.Salvatore
*
* @author leechenxiang
* @date 2016年12月12日 下午7:25:40
* @version V1.0
*/
public class KickoutSessionControlFilter extends AccessControlFilter { private String kickoutUrl; //踢出后到的地址
private boolean kickoutAfter = false; //踢出之前登录的/之后登录的用户 默认踢出之前登录的用户
private int maxSession = 1; //同一个帐号最大会话数 默认1 private SessionManager sessionManager;
private Cache<String, Deque<Serializable>> cache; public void setKickoutUrl(String kickoutUrl) {
this.kickoutUrl = kickoutUrl;
} public void setKickoutAfter(boolean kickoutAfter) {
this.kickoutAfter = kickoutAfter;
} public void setMaxSession(int maxSession) {
this.maxSession = maxSession;
} public void setSessionManager(SessionManager sessionManager) {
this.sessionManager = sessionManager;
} public void setCacheManager(CacheManager cacheManager) {
this.cache = cacheManager.getCache("shiro-kickout-session");
} @Override
protected boolean isAccessAllowed(ServletRequest request, ServletResponse response, Object mappedValue) throws Exception {
return false;
} @Override
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();
ActiveUser user = (ActiveUser)subject.getPrincipal();
String username = user.getUserName();
Serializable sessionId = session.getId(); // 同步控制
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); HttpServletRequest httpRequest = WebUtils.toHttp(request);
if (ShiroFilterUtils.isAjax(httpRequest)) {
HttpServletResponse httpServletResponse = WebUtils.toHttp(response);
httpServletResponse.sendError(ShiroFilterUtils.HTTP_STATUS_SESSION_EXPIRE);
return false;
} else {
WebUtils.issueRedirect(request, response, kickoutUrl);
return false;
}
} return true;
}
}
首先得要有个过滤器命名为:KickoutSessionControlFilter
然后在shiro.xml中需要这么定义:
<property name="filters">
<map>
<entry key="kickout" value-ref="kickoutSessionControlFilter"/>
</map>
</property>
<bean id="kickoutSessionControlFilter" class="com.agood.bejavagod.controller.filter.KickoutSessionControlFilter">
<property name="cacheManager" ref="shiroEhcacheManager"/>
<property name="sessionManager" ref="sessionManager"/>
<!-- 是否踢出后来登录的,默认是false;即后者登录的用户踢出前者登录的用户 -->
<property name="kickoutAfter" value="false"/>
<!-- 同一个用户最大的会话数,默认1;比如2的意思是同一个用户允许最多同时两个人登录 -->
<property name="maxSession" value="1"/>
<property name="kickoutUrl" value="/login.action"/>
</bean>
最后修改过滤器配置,拦截所有请求
/** = kickout,authc
Shiro - 限制并发人数登录与剔除的更多相关文章
- 项目一:第十一天 2、运单waybill快速录入 3、权限demo演示-了解 5、权限模块数据模型 6、基于shiro实现用户认证-登录(重点)
1. easyui DataGrid行编辑功能 2. 运单waybill快速录入 3. 权限demo演示-了解 4. Apache shiro安全框架概述 5. 权限模块数据模型 6. 基于shiro ...
- shiro中接入单点登录功能
最近新建的系统中使用了shiro,而shiro框架中包含登录认证和鉴权的功能,因为我们系统要统一接入公司内部的单点登录(isso)系统,所以通过isso的登录用户,需要在shiro中置为已认证,一下提 ...
- 2017.6.30 用shiro实现并发登录人数控制(实际项目中的实现)
之前的学习总结:http://www.cnblogs.com/lyh421/p/6698871.html 1.kickout功能描述 如果将配置文件中的kickout设置为true,则在另处再次登录时 ...
- Shiro学习(18)并发人数限制
在某些项目中可能会遇到如每个账户同时只能有一个人登录或几个人同时登录,如果同时有多人登录:要么不让后者登录:要么踢出前者登录(强制退出).比如spring security就直接提供了相应的功能:Sh ...
- (一)shiro简介和用户登录demo及角色管理
一.shiro简介 Apache Shiro是Java的一个安全框架.Shiro可以非常容易的开发出足够好的应用,其不仅可以用在JavaSE环境,也可以用在JavaEE环境.Shiro可以帮助我们完成 ...
- shiro 实现单用户登录,一个用户同一时刻只能在一个地方登录
我这里 shiro 并没有集成 springMVC,直接使用 ini 配置文件. shiro.ini [main] # Objects and their properties are defined ...
- Shiro+easyUI+SpringMVC实现登录认证
最近在做一个小项目,其中认证这块使用shiro+SpringMVC+easyUI,因为easyUI在提交数据的时候使用的是ajax的异步提交,所以shiro在处理数据的时候需要重写FormAuth ...
- Shiro源码解析-登录篇
本文以循序渐进的方式解析Shiro整个login过程的处理,读者可以边阅读本文边自己看代码来思考体会,如有问题,欢迎评论区探讨! 笔者shiro的demo源码路径:https://github.com ...
- springboot+shiro+cas实现单点登录之shiro端搭建
github:https://github.com/peterowang/shiro-cas 本文如有配置问题,请查看之前的springboot集成shiro的文章 1.配置ehcache缓存,在re ...
随机推荐
- Collection框架
Collection框架 集合框架(Collection Framework)泛指java.util包的若干个类和接口.如Collection,List,ArrayList,LinkedList,Ve ...
- 第 31 章 项目实战-PC端固定布局[1]
学习要点: 1.准备工作 2.创建项目 3.网站结构 4.CSS选择器 5.完成导航 主讲教师:李炎恢 本章主要开始使用学习用HTML5和CSS3来构建Web页面,第一个项目采用PC端 固定布局来实现 ...
- PHP工作笔记:yii2各种功能汇总
数据库操纵: 基础知识:数据库基础 查询语句: 使用yii migrate管理.生成数据库 Yii2 AR find用法 Yii2.0 对数据库 查询的一些简单的操作 修改语句: Yii 修改数据的两 ...
- 【JAVA并发编程实战】9、锁分段
package cn.study.concurrency.ch11; /** * 锁分段 * @author xiaof * */ public class StripedMap { //同步策略:就 ...
- python征程3.0(python对象)
1.python使用对象模型来存储数据.构造任何类型的值都是一个对象.”尽管python被当成一种面向对象的脚本的编程语言“,但你完全能够写出不使用任何类和实例的脚本. python对象都拥有三个特性 ...
- 使用C#开发数据库应用系统
第一章 初识Windows程序 01.浅谈控制台应用 解析:控制台应用程序:dos窗口中显示 Windows窗体应用程序:有控件参与的,支持事件的一种程序 02.关于窗体项目的注意点: /*01.一个 ...
- 前端学习笔记——移动前端UI选择
一.jQuery Mobile jQuery Mobile 是jQuery在移动设备上的版本,做为主要针对移动设备的框架来说,它提供一个移动设备平台统一的接口来兼容不同的移动平台,其特性包括: 1.简 ...
- jQuery基础知识总结
1. jQuery基本概念介绍 1.1 什么是jQuery 一个javascript库,把常用方法写到一个js文件中,需要的时候直接调用即可 学习jQuery就是学习一些方法 ...
- 天津政府应急系统之GIS一张图(arcgis api for flex)讲解(六)地图搜索模块
config.xml文件的配置如下: <widget label="地图搜索" icon="assets/images/emergency_resource_ove ...
- 天津政府应急系统之GIS一张图(arcgis api for flex)讲解(五)地图切换以及图层显示模块
config.xml文件的配置如下: <widget right="20" top="55" config="widgets/MapSwitch ...