我的shiro之旅: 十二 shiro 踢出用户(同一用户只能一处登录)

shiro注销其他用户_Shiro实现互斥登录,并踢出登录用户功能。 作为一名小白,初遇到这种业务也着实头疼了一段时间。经历了各种查资料,总结出了一个相对简便的方法。首先在登陆之后使用Collection list = sessionDAO.getActiveSessions();方法获取到所有登录的用户,循环该list,取到集合中单个的session对象Subject s = new Subject.Builder().session(session).build... 阅读详情

博客已移至 http://blog.gogl.top

看了一下官网,没有找到关于如何控制同一用户只能一处登录的介绍,网上也没有找到相关的文章。可能有些人会记录用户的登录信息,然后达到踢出用户的效果。这里介绍一个更简单的方法。

如果我们跟shiro的源码,我们可以看到。当用户登录成功后,shiro会把用户名放到session的attribute中,key为DefaultSubjectContext_PRINCIPALS_SESSION_KEY,这个key的定义是在shiro的org.apache.shiro.subject.support.DefaultSubjectContext中,这个类有三个public的静态属性,其他都为private。其中PRINCIPALS_SESSION_KEY这个属性记录的是用户名,而AUTHENTICATED_SESSION_KEY属性记录的是用户认证,当用户登录成功后,这个attribute的值是true。

曾经我想把AUTHENTICATED_SESSION_KEY这个attribute的值设置为false,表示用户是退出状态,这样达到退出用户的目的,不过没有成功,shiro判断用户是否是登录状态并不从这里判断。不过既然我们可以通过用户名可以找到用户对应的session,也很容易将该session删除,让用户重新建立一个新的sesison。这里给出一个帮助类,带有跳出用户的功能。

        

package com.concom.security.infrastructure.helper;

import java.util.Collection;

import org.apache.commons.lang.StringUtils;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.session.Session;
import org.apache.shiro.session.mgt.eis.SessionDAO;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.subject.Subject;
import org.apache.shiro.subject.support.DefaultSubjectContext;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.concom.lang.helper.TimeHelper;
import com.concom.security.application.memcache.CurrentUserMemcacheService;
import com.concom.security.application.user.UserService;
import com.concom.security.domain.user.User;

/**
 * @author Dylan
 * @time 2013-8-12
 */
public class ShiroSecurityHelper {
	
	private final static Logger log = LoggerFactory.getLogger(ShiroSecurityHelper.class);

	private static UserService userService;

	private static CurrentUserMemcacheService currentUserMemcacheService;
	
	private static SessionDAO sessionDAO;

	/**
	 * 把user放到cache中
	 * 
	 * @param user
	 */
	public static void setUser(User user) {
		currentUserMemcacheService.save(user);
	}

	/**
	 * 清除当前用户的缓存
	 */
	public static void clearCurrentUserCache() {
		if (hasAuthenticated()) {
			currentUserMemcacheService.remove(getCurrentUsername());
		}
	}

	/**
	 * 从cache拿当前user
	 * 
	 * @return
	 */
	public static User getCurrentUser() {
		if (!hasAuthenticated()) {
			return null;
		}
		User user = currentUserMemcacheService.get(getCurrentUsername());
		try {
			if (null == user) {
				user = userService.getByUsername(getCurrentUsername());
				ShiroSecurityHelper.setUser(user);
			}
			return user;
		} catch (Exception e) {
			e.printStackTrace();
			return null;
		}
	}

	/**
	 * 获得当前用户名
	 * 
	 * @return
	 */
	public static String getCurrentUsername() {
		Subject subject = getSubject();
		PrincipalCollection collection = subject.getPrincipals();
		if (null != collection && !collection.isEmpty()) {
			return (String) collection.iterator().next();
		}
		return null;
	}

	/**
	 * 
	 * @return
	 */
	public static Session getSession() {
		return SecurityUtils.getSubject().getSession();
	}

	/**
	 * 
	 * @return
	 */
	public static String getSessionId() {
		Session session = getSession();
		if (null == session) {
			return null;
		}
		return getSession().getId().toString();
	}
	
	/**
	 * @param username
	 * @return
	 */
	public static Session getSessionByUsername(String username){
		Collection<Session> sessions = sessionDAO.getActiveSessions();
		for(Session session : sessions){
			if(null != session && StringUtils.equals(String.valueOf(session.getAttribute(DefaultSubjectContext.PRINCIPALS_SESSION_KEY)), username)){
				return session;
			}
		}
		return null;
	}
	
	/**踢除用户
	 * @param username
	 */
	public static void kickOutUser(String username){
		Session session = getSessionByUsername(username);
		if(null != session && !StringUtils.equals(String.valueOf(session.getId()), ShiroSecurityHelper.getSessionId())){
			ShiroAuthorizationHelper.clearAuthenticationInfo(session.getId());
			log.info("############## success kick out user 【{}】 ------ {} #################", username,TimeHelper.getCurrentTime());
		}
	}

	/**
	 * @param userService
	 * @param currentUserMemcacheService
	 * @param sessionDAO
	 */
	public static void initStaticField(UserService userService,CurrentUserMemcacheService currentUserMemcacheService,SessionDAO sessionDAO){
		ShiroSecurityHelper.userService = userService;
		ShiroSecurityHelper.currentUserMemcacheService = currentUserMemcacheService;
		ShiroSecurityHelper.sessionDAO = sessionDAO;
	}
	
	/**
	 * 判断当前用户是否已通过认证
	 * @return
	 */
	public static boolean hasAuthenticated() {
		return getSubject().isAuthenticated();
	}

	private static Subject getSubject() {
		return SecurityUtils.getSubject();
	}


}

 

再通过spring注入帮助类需要的静态属性。

 

	<bean class="org.springframework.beans.factory.config.MethodInvokingFactoryBean">
		<property name="staticMethod" value="com.concom.security.infrastructure.helper.ShiroSecurityHelper.initStaticField" />
		<property name="arguments">
			<list>
				<ref bean="userService"/>
				<ref bean="currentUserMemcacheService"/>
				<ref bean="sessionDAO"/>
			</list>
		</property>
	</bean>


读者可以不关注userService,currentUserMemcacheService,其中踢出功能用到了SessionDAO,定义可能看我的shiro之旅: 七 shiro session 共享,文章里的spring配置文件有介绍,这里不再作描述。从这个类名我们就可以猜想到,这个类是用户管理session的。ShiroAuthorizationHelper这个帮助类在我的shiro之旅: 九 shiro 清理缓存的权限信息这篇文章介绍到。通过用户名使用用户对应的session,然后将该session删除,这个kickOutUser方法应该在用户登录之前调用。

 

session删除后,当用户再请求服务器时,服务端shiro会抛出there is no session的异常,然后从新为请求建立一个新的session,就像用户很长时间没有点击浏览器,shiro的定时器定时将失效的session清除的时候也抛出这个异常一样。不过这个对用户是透明的,对用户的体验没有影响。

这是其中的一种方式,也许有更好的实现方式。如果读者有更好的实现方式,希望能与我分享。

spring boot + shiro 实现单点登陆/并发登入控制 踢出用户功能(禁止用户多点登录或重复登录) 需求: springboot整合shiro项目。因为shiro只是一个Java安全框架,并不会做重复登录的拦截,当一个用户登录成功后(chrome登录),再用另外一个浏览器登录(IE登录)或者另外一台电脑进行登录,两个都会登录成功,两个不同的session。 预期目的:不允许重复登录,限定一个账号一个用户登陆,并且是挤掉前一个用户(踢出用户),保证一个帐号只能同时一个人使用,例如微信和qq等。 预设解决方法:当第二次登录时,把第一个session剔除 使用的技术其实是 shiro的自定义filter,在sh 阅读详情

相关推荐

关于shiro同一帐号同一时刻多处登录问题

这段时间做项目遇到一个关于shiro登录的问题。同一帐号不能同时登录,如果同时登录的话前面一个人的session就失效。百转千回,因为shiro登录到权限控制没有任何问题,就把问题点转移到存储端。去检查redis,检查reids的配置相关,结果也没发现什么毛病。后来在网上查阅文章,多看了看shiro相关的东西。问题锁定在shiro控制同一用户不能在同一时刻多处登录,然后修改程序: 1.s

henry_chatter的博客 7071

shiro实现用户踢出,在线用户列表展示功能,包含常见踩坑集合、代码下载

功能描述:用户a登录了s账号,接着用户b也登录了s账号,此时用户a将被踢出。一个账号只能一个人登录,被别人登录了,那么你就要被踢下线。 shiro认证与授权理解 用户在登录的时候只执行认证方法而没有马上去执行授权doGetAuthorizationInfo()方法。 shiro并不是在认证之后就马上对用户授权,而是在用户认证通过之后,接下来要访问的资源或者目标方法需要权限的时候才会调用doGetAuthorizationInfo()方法,进行授权. 比如当认证通过后,访问@RequiresPermis.

风团团 1538

遇到问题----shrio------shiro登录,多个项目session被覆盖问题---两个web项目会导致shiro的session污染

情况遇到问题----shrio------shiro登录,多个项目session被覆盖问题---一个项目两个web模块会导致shiro的session污染表现为 我在同一台机子上部署了两个都使用了shiro管理的web项目。它们的访问路径除了端口不一样,ip是一样的。当两个系统同时访问时,在一个系统中操作之后另一个系统就会自动退出登录。但是 如果用域名访问就不会出现这个问题。原因web项目的ses

直到世界的尽头 1万+

shiro源码分析

接上一篇,https://blog.youkuaiyun.com/luxinghong199106/article/details/105707188 这一篇主要通过2个流程,一个登录流程和一个登陆成功后的访问流程来看下 subject 的创建过程。因为subject 是 shiro 的核心,搞懂了它的创建过程,基本就搞懂了 shiro 的核心逻辑。(这一部分代码是基于传统表单验证的,不是基于JWT的) ...

luxinghong199106的博客 560

新手避坑指南:用Silvaco Atlas搞定GaN HEMT电热仿真的完整流程(附代码解读)

本文详细介绍了使用Silvaco Atlas进行GaN HEMT电热特性仿真的完整流程,特别针对新手常见问题提供避坑指南。从软件环境配置、结构定义、网格划分到物理模型设置,逐步解析关键步骤,并附有代码解读和调试技巧,帮助读者快速掌握GaN器件仿真的核心技术。

weixin_29215815的博客 597

Ubuntu中 vsftpd 的安装与配置 (详细介绍)

简介 vsftpd 是一个 UNIX 类操作系统上运行的服务器的名字,它可以运行在诸如 Linux, BSD, Solaris, HP-UX 以及 IRIX 上面。它支持很多其他的 FTP 服务器不支持的特征。 vsftpd是 UNIX 操作系统中的一个开源的、免费的 FTP 服务软件。具有以下特点: 安全性高 轻小易用 支持系统用户匿名用户和虚拟用户的权限验证和相关操作 安装步骤如下: 1.将此命令复制到终端 sudo apt-get install vsftpd 2.安装完成后启动VSFTP

qq_43299421的博客 1万+

Shiro中的session学习,在线用户显示、用户下线

一、代码示例 import org.apache.shiro.session.Session; import org.apache.shiro.session.mgt.eis.SessionDAO; import org.apache.shiro.subject.SimplePrincipalCollection; import org.apache.shiro.subject.suppo...

程序员小嗨 3553

硬件单板类机考复习提纲

6、 功率晶体管低导通损耗时处于的状态(饱和状态、放大状态、截止状态)(放大器的采样频率特性)总结:元器件特性(电阻、电容、二极管、三极管、晶体、晶振、MOS、磁珠等)信号质量问题产生根因(单调性、边沿过缓、毛刺、回沟、抖动等)3、 几种电容容量范围大小(超级电容、钽电容、陶瓷电容、铝电容)66、背板连接器接触设计的接触顺序(先导向、再地针、最后信号针)28、逻辑电平接口的特性(CMOS、TTL、ECL、PECL)76、差分电平(lvpecl、RS-422/485、cml)

2303_79562407的博客 1万+

shiro 删除用户session_我的shiro之旅: 十二 shiro 踢出用户(同一用户只能一处登录)...

看了一下官网,没有找到关于如何控制同一用户只能一处登录的介绍,网上也没有找到相关的文章。可能有些人会记录用户的登录信息,然后达到踢出用户的效果。这里介绍一个更简单的方法。如果我们跟shiro的源码,我们可以看到。当用户登录成功 后,shiro会把用户名放到session的attribute中,key为 DefaultSubjectContext_PRINCIPALS_SESSION_KEY,这个k...

weixin_29111593的博客 833

手把手教你用野火FPGA开发板资料包安装ModelSim 10.5se(附破解教程)

本文提供了一份详细的指南,手把手教你为野火FPGA开发板安装和配置ModelSim 10.5se仿真工具。内容涵盖从前期准备、软件安装、许可证激活(学习用途)到环境验证的全过程,并简要介绍了如何与Xilinx Vivado开发套件集成,帮助初学者快速搭建稳定的FPGA仿真环境。

lstm7chronicler的博客 250

VLSI数字信号处理系统——第九章滤波器和变换中的算法强度缩减

[课程学习] VLSI数字信号处理系统——第九章滤波器和变换中的算法强度缩减

夏风喃喃的博客 1604

jeesite限制用户只能在一处登录

jeesite限制用户只能在一处登录 /** * 授权查询回调函数, 进行鉴权但缓存中无用户的授权信息时调用 */ @Override protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principals) { Principal principal = (Principal) ge...

isduxd的博客 1262

Vectorless dynamic动态功耗分析——Voltus

power 计算工具会根据设计信息和用户提供的activity和switching约束来生成虚拟的worst-case的power vector,难点在于哪些instances视为switching,在没有仿真的前提下如何确定开关的时间,使用timing文件(TWF)

qq_44347276的博客 2790

shiro同一用户后登陆踢出前面的用户

直接上代码 下面就是我实现的访问控制拦截器:KickoutSessionControlFilter: public class KickoutSessionControlFilter extends AccessControlFilter { private static Logger logger = LoggerFactory.getLogger(KickoutSessionContro...

qq_40543150的博客 3571

VL53L0X测距不准?手把手教你做RefSPAD校准与环境补偿(附Arduino/STM32代码)

本文详细解析了VL53L0X激光测距传感器精度不足的原因,并提供了RefSPAD校准与环境补偿的完整解决方案。通过Arduino和STM32代码示例,手把手教你实现毫米级测距稳定性,适用于机器人避障、工业检测等场景。

weixin_28744423的博客 257

【INMP441】 MEMS麦克风,让硬件“听得见”,更要“听得清”

INMP441是一款数字MEMS麦克风,采用PDM接口输出高质量数字音频信号。相比传统模拟麦克风,它具有高度集成、抗干扰强、功耗低等优势,支持通过时钟启停实现软件控制开关。该麦克风体积小巧但功能强大,内置MEMS传感器、ADC转换器等模块,适合智能音箱、语音遥控等应用。工程师可通过ESP32等主控芯片轻松连接INMP441,利用多麦克风阵列实现波束成形等高级功能。INMP441展现了数字音频采集的先进技术,为创客和智能硬件开发者提供了优秀的音频解决方案。

深耕CV 1536

springboot shiro session互踢功能,一个用户只能一处浏览器登录

说明:一个相同的账号在第一个浏览器登陆成功后,当在第二浏览器登陆成功后,第一个浏览器登陆的用户就会被踢出,无法进行操作。 主要是配置EhCache缓存器来缓存sission 1、shiro 配置Javabean,ShiroConfiguration.java import java.util.LinkedHashMap; import java.util.Map; import or...

风兮雨露的博客 6140

复分析 阿尔福斯(Ahlfors) 第三版答案 英文

答案分为十章,有部分习题没有答案,全英文复分析阿尔福斯(Ahlfors) 第三版答案

Shiro 通过处理session,实现一个账号只能一处登录问题

文章目录1. 问题2. 原因3. 解决 1. 问题 在处理一个账号只能一处登录时,登录会出现异常,如下 14:51:44.689] DEBUG org.springframework.web.servlet.FrameworkServlet 991 processRequest - Could not complete request org.apache.shiro.session.Unknow...

爱折腾的Albert 2832

Devexpress16.2.6破解工具

Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具

SAP B1中文培訓教材_SDK

公司内部培训资料,对开发工具 ,DIAPI, UIAPI,Add-ON有详细解说

SpringBoot+Shiro学习之自定义拦截器管理在线用户(踢出用户)

应用场景 我们经常会有用到,当A 用户在北京登录 ,然后A用户在天津再登录 ,要踢出北京登录的状态。如果用户在北京重新登录,那么又要踢出天津的用户,这样反复。又或是需要限制同一用户的同时在线数量,超出限制后,踢出最先登录的或是踢出最后登录的。 第一个场景踢出用户是由用户触发的,有时候需要手动将某个在线用户踢出,也就是对当前在线用户的列表进行管理。 ··························

qq_20954959的博客 1万+

Shiro实现互斥登录,并踢出登录用户功能。

作为一名小白,初遇到这种业务也着实头疼了一段时间。经历了各种查资料,总结出了一个相对简便的方法。 首先在登陆之后使用 Collection<Session> list = sessionDAO.getActiveSessions(); 方法获取...

1622

shiro session互踢,一个用户只能一处登录

shiro 实现redis共享session, 一个用户只能一处登录 shiro 核心类AuthorizingRealm, 自己写一个类AuthRealm继承AuthorizingRealm @Override protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken token) throws Authe...

liuzhen_333的专栏 7466

shiro获取session用户_apache shiro踢出用户和获取所有在线用户

apache shiro踢出用户:产品要求用户只能在同一个地方登录,如果之前在其他机器或者浏览器上登录,讲之前登录帐号踢出。applicationContext-shiro.xml配置:在默认的shiro配置上增加如下配置(本文假设你已经使用过apache shiro,并且已经使用shiro成功实现登录功能):然后在ShiroDbRealm中的认证方法中增加如下代码,代码主要目的就是根据当前登录名...

weixin_39634052的博客 1175

shiro ajax springmvc,SpringMVC + Shiro实现用户踢出功能

整理自己的代码片段的时候, 想起来之前有一个需求: 实现同一个用户同时只能在一个地方登陆, 如果该用户在其他地方登陆, 踢出前一个登陆状态。项目中使用的是shiro做为权限控制框架, 对此需求进行了一些实现, 思路如下: shiro是利用一个个filter进行过滤请求的权限, 那么我就可以自定义一个filter在用户登陆之后, 判断当前的用户是否存在已经登陆的情况, 如果已经存在, 那么就踢出。代...

weixin_40001309的博客 462

SpringBoot+shiro+redis 一个账户只允许一处登录,强制用户下线

SpringBoot+shiro+redis 一个账户只允许一处登录,强制用户下线 概况 前期引入了redis来解决session共享,但并么有限制一个账户多人同时在线,且shiro本身没有带这个控制功能。在网上找了其他人的思路,但效果都有点不太好,于是自己写一下自己的项目实战。(第一次分享,希望各位大神多多指教)。 于是乎,利用redis 来记录一个用户的sessionID,如果一个用户存在多个sessionId,则获取队列末尾的sessionId,用sessionId查询对应的session,给sess

weixin_43823332的博客 3610

shiro单用登录(同一时刻只能登录一个账号)

(一)applicationContext-shiro.xml <bean id="myRealm" class="com.sys.shiro.MyRealm" /> <bean id="sessionDAO" class="org.apache.shiro.session.mgt.eis.MemorySessionDAO"> </bean> ...

布谷鸟 2460
上一篇: 我的shiro之旅: 十一 shiro的权限设计
下一篇: 我的shiro之旅: 十三 shiro 用户的登录与退出
LHacker
博客等级 码龄17年 162粉丝 24原创
评论 9
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值