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

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

如果我们跟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 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注入帮助类需要的静态属性。

读者可以不关注userService,currentUserMemcacheService,其中踢出功能用到了SessionDAO,定义可能看我的shiro之旅: 七 shiro session 共享,文章里的spring配置文件有介绍,这里不再作描述。从这个类名我们就可以猜想到,这个类是用户管理session的。ShiroAuthorizationHelper这个帮助类在我的shiro之旅:

九 shiro 清理缓存的权限信息这篇文章介绍到。通过用户名使用用户对应的session,然后将该session删除,这个kickOutUser方法应该在用户登录之前调用。

session删除后,当用户再请求服务器时,服务端shiro会抛

出there is no

session的异常,然后从新为请求建立一个新的session,就像用户很长时间没有点击浏览器,shiro的定时器定时将失效的session清除

的时候也抛出这个异常一样。不过这个对用户是透明的,对用户的体验没有影响。

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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值