Shiro单用户登录,清理之前登录的用户

本文详细探讨了Apache Shiro框架如何实现单用户登录功能,通过清理旧Session来确保同一用户只能有一个在线会话。代码示例展示了如何获取并遍历所有活跃Session,删除除当前用户Session外的其他Session,以实现单点登录的效果。方法一是通过User对象,方法二是通过userName字符串,两种方式都确保了用户登录的唯一性。

刨析 Shiro 的 SecurityManager 实现单用户登录

通过这个可以看出 SecurityManager 中存储了那些 SessionId ,

public void getShiroManagerCache() {
	System.out.println("查询保存到ShiroManagerCache的SessionId为~");
	String currentUserSessionId = SecurityUtils.getSubject().getSession().getId().toString();
	System.out.println(currentUserSessionId);
	CrmSysUser user = (CrmSysUser) SecurityUtils.getSubject().getPrincipal();
	DefaultWebSecurityManager securityManager = (DefaultWebSecurityManager) SecurityUtils.getSecurityManager();
	DefaultWebSessionManager sessionManager = (DefaultWebSessionManager) securityManager.getSessionManager();
	Collection<Session> sessions = sessionManager.getSessionDAO().getActiveSessions();
	if (sessions.size() > 1) {
		for (Session onlineSession : sessions) {
			System.out.println("SessionId为[" + onlineSession.getId() + "]的Session信息!");
		}
	}
}

在这里插入图片描述

Shiro单用户登录,清理之前登录的用户 ,以下的方法会清除掉其他的 SessionId

/**
*	new SimpleAuthenticationInfo(user, pwd, this.getName())中的第一个参数是SysUser对象,
*	在其他接收的地方也要转成SysUser对象,使用对象这里对应的处理方式是采用方法一,
*	如果是传递的userName字符串,则采用方法二进行处理
*/
SimpleAuthenticationInfo authcInfo = new SimpleAuthenticationInfo(user, pwd, this.getName()); 

方法一:传入的参数是User对象

/**
 * @功能描述:	单用户登录,清除当前用户以前登录时保存的session会话
 * @param loginName
 */
public void singleUseLogin(String loginName){
	// 1.获取当前用户sessionId
	String currentUserSessionId = SecurityUtils.getSubject().getSession().getId().toString();

	// 2.获取shiro的sessionManager
	DefaultWebSecurityManager securityManager = (DefaultWebSecurityManager) SecurityUtils.getSecurityManager();
	DefaultWebSessionManager sessionManager = (DefaultWebSessionManager)securityManager.getSessionManager();

	// 3.获取所有已登录用户的session列表
	Collection<Session> sessions = sessionManager.getSessionDAO().getActiveSessions();

	if (sessions.size() > 1) {
		System.out.println("仅允许单用户登录,开始清理遗留用户信息~");
		User user = null;
		for(Session onlineSession:sessions){
			// 4. 获取已登录用户的session的key值
			SimplePrincipalCollection simplePrincipalCollection = (SimplePrincipalCollection) onlineSession.getAttribute(DefaultSubjectContext.PRINCIPALS_SESSION_KEY);
			if (null == simplePrincipalCollection) {
				sessionManager.getSessionDAO().delete(onlineSession);
				continue;
			}
			// 5. 获取new SimpleAuthenticationInfo(user, pwd, this.getName())中放进去的第一个参数
			user = (User) simplePrincipalCollection.getPrimaryPrincipal();

			// 6. 清除当前用户以前登录时保存的session会话
			if (loginName.equals(user.getUserName()) && !onlineSession.getId().equals(currentUserSessionId)) {
				sessionManager.getSessionDAO().delete(onlineSession);
				System.out.println("清理用户["+loginName+"],SessionId为["+onlineSession.getId()+"]的Session信息!");
			}
		}
	} else {
		System.out.println("无可清理用户信息~");
	}
}

方法二:传入的参数是userName字符串

登录后复制
/**
 * @功能描述:	单用户登录,清除当前用户以前登录时保存的session会话
 * @param loginName
 */
public void singleUseLogin(HttpServletRequest request,String loginName){
	// 1.获取当前用户sessionId
	String currentUserSessionId = request.getSession().getId();

	// 2.获取shiro的sessionManager
	DefaultWebSecurityManager securityManager = (DefaultWebSecurityManager) SecurityUtils.getSecurityManager();
	DefaultWebSessionManager sessionManager = (DefaultWebSessionManager)securityManager.getSessionManager();

	// 3.获取所有已登录用户的session列表
	Collection<Session> sessions = sessionManager.getSessionDAO().getActiveSessions();

	// 处理方法一:UserRalm中传入的是userName使用此方法
	String onlineSessionKey = "";
	for(Session onlineSession:sessions){
		// 4.获取已登录用户的session的key值
		onlineSessionKey = String.valueOf(onlineSession.getAttribute(DefaultSubjectContext.PRINCIPALS_SESSION_KEY));
		// 5.清除当前用户以前登录时保存的session会话
		System.out.println(onlineSession.getId()+"------" + onlineSessionKey);

		if (onlineSessionKey.equals("null")) {
			sessionManager.getSessionDAO().delete(onlineSession);
		} else if (loginName.equals(onlineSessionKey) && !onlineSession.getId().equals(currentUserSessionId)) {
			sessionManager.getSessionDAO().delete(onlineSession);
		}
	}
}

方法二,优化版

/**
 * @功能描述:   单用户登录,清除当前用户以前登录时保存的session会话
 * @param loginName
 */
public void singleUseLogin(String loginName){
    // 1.获取当前用户sessionId
    String currentUserSessionId = SecurityUtils.getSubject().getSession().getId().toString();
    // 2.获取当前用户
    User user = (User) SecurityUtils.getSubject().getPrincipal();
    // 3.获取shiro的sessionManager
    DefaultWebSecurityManager securityManager = (DefaultWebSecurityManager) SecurityUtils.getSecurityManager();
    DefaultWebSessionManager sessionManager = (DefaultWebSessionManager)securityManager.getSessionManager();
    // 4.获取所有已登录用户的session列表
    Collection<Session> sessions = sessionManager.getSessionDAO().getActiveSessions();
 
    if (sessions.size() > 1) {
        System.out.println("仅允许单用户登录,开始清理遗留用户信息~");
        for(Session onlineSession:sessions){
            // 5. 清除当前用户以前登录时保存的session会话
            if (loginName.equals(user.getUserName()) && !onlineSession.getId().equals(currentUserSessionId)) {
                sessionManager.getSessionDAO().delete(onlineSession);
                System.out.println("清理用户["+loginName+"],SessionId为["+onlineSession.getId()+"]的Session信息!");
            }
        }
    } else {
        System.out.println("无可清理用户信息~");
    }
}
# 这个的底层的作者还在继续深入研究 中,想看看能不能仿照写一个进行学习
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

IT小郭.

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值