Java实现用户异地登陆踢人操作

使用框架:Shiro+SpringBoot

首先,我先说步骤:

1.登陆

2.查看该用户是否已经登陆 是:3   否:正常登陆

3.将已登陆用户踢出,自己登陆。

这只是说原理,具体实现现在说。


踢出已登陆用户,主要体现在对已登陆用户session的处理上,原理简单,就是将已登陆用户的session删除就好。

难点在于如何找到该用户的session。

这里,我使用了redis

首先,在登陆的时候获取用户的sessionId,也就是浏览器中的jessionId,因为我使用的是shiro框架,方法如下:

 Subject user = SecurityUtils.getSubject();

        UsernamePasswordToken token = new UsernamePasswordToken(phone, MD5Utils.getMD5Str(password).toCharArray());  //DigestUtils.md5Hex(password).toCharArray());//
        token.setRememberMe(true);
        try {
            user.login(token);
            user.getSession().setTimeout(-1000L); // 开发时设置永不过期,上线时需要调整 todo

        } catch (UnknownAccountException e) {
            logger.error("账号不存在:{}", e);
            return new ChariotResponseEntity<>(ChariotHttpStatus.USER_ACCOUNT_OR_PASSWORD_ERROR);
        } catch (DisabledAccountException e) {
            logger.error("账号未启用:{}", e);
            return new ChariotResponseEntity<>(ChariotHttpStatus.USER_NOT_ENABLED);
        } catch (IncorrectCredentialsException e) {
            logger.error("密码错误:{}", e);
            return new ChariotResponseEntity<>(ChariotHttpStatus.USER_ACCOUNT_OR_PASSWORD_ERROR);
        } catch (RuntimeException e) {
            logger.error("未知错误,请联系管理员:{}" + e.toString(), e);
            System.out.println(e.toString());
            return new ChariotResponseEntity<>(ChariotHttpStatus.USER_OTHER_REASON);
        }

        SessionsSecurityManager securityManager = (SessionsSecurityManager) SecurityUtils.getSecurityManager();

        DefaultSessionManager sessionManager = (DefaultSessionManager) securityManager.getSessionManager();

        String sessionId = String.valueOf(user.getSession().getId());

主要是其中这段

        SessionsSecurityManager securityManager = (SessionsSecurityManager) SecurityUtils.getSecurityManager();

        DefaultSessionManager sessionManager = (DefaultSessionManager) securityManager.getSessionManager();

        String sessionId = String.valueOf(user.getSession().getId());

拿到当前登陆用户的sessionId之后,就该获取存入redis中的在这之前登陆的用户的sessionId,

这里我要解释一下sessionId的存取的现实操作步骤:

(背景:A用户没有登陆。)

1.A用户登陆,并获取A用户的sessionId

  Subject user = SecurityUtils.getSubject();

        UsernamePasswordToken token = new UsernamePasswordToken(phone, MD5Utils.getMD5Str(password).toCharArray());  //DigestUtils.md5Hex(password).toCharArray());//
//        token.setRememberMe(true);
        try {
            user.login(token);
            user.getSession().setTimeout(7*24*3600*1000); // 开发时设置永不过期,上线时需要调整 todo
        } catch (UnknownAccountException e) {
            logger.error("账号不存在:{}", e);
            return new ChariotResponseEntity<>(ChariotHttpStatus.USER_ACCOUNT_OR_PASSWORD_ERROR);
        } catch (DisabledAccountException e) {
            logger.error("账号未启用:{}", e);
            return new ChariotResponseEntity<>(ChariotHttpStatus.USER_NOT_ENABLED);
        } catch (IncorrectCredentialsException e) {
            logger.error("密码错误:{}", e);
            return new ChariotResponseEntity<>(ChariotHttpStatus.USER_ACCOUNT_OR_PASSWORD_ERROR);
        } catch (RuntimeException e) {
            logger.error("未知错误,请联系管理员:{}" + e.toString(), e);
            System.out.println(e.toString());
            return new ChariotResponseEntity<>(ChariotHttpStatus.USER_OTHER_REASON);
        }

        SessionsSecurityManager securityManager = (SessionsSecurityManager) SecurityUtils.getSecurityManager();

        DefaultSessionManager sessionManager = (DefaultSessionManager) securityManager.getSessionManager();

        String sessionId = String.valueOf(user.getSession().getId());//这个就是A的sessionId

2.从redis根据条件获取sessionId,当然,因为之前并没有存入,所以获取不到,这里的条件是phone+“redist“,保证唯一

 String sessionId2 = jedisConfiguration.getJedisClient().get(phone+"redis");

3.判断sessionId2是否为空,如果为空的话,就走第4步,否则,就先根据sessionId2获取sessionKey,再根据sessionKey获取session,然后根据sessionManager删除指定session,也就是我们希望踢掉的用户的session

if(StringUtil.isNotEmpty(sessionId2)) {

            SessionKey sessionKey = new WebSessionKey(jedisConfiguration.getJedisClient().get(phone+"redis"),request,response);
            try {
                Session session = securityManager.getSession(sessionKey);
                if(!sessionId.equals(sessionId2))
                    sessionManager.getSessionDAO().delete(session);
            }catch (Exception e){
                e.printStackTrace();
             }

            jedisConfiguration.getJedisClient().del(phone+"redis");

        }

4.这步也就结束了,将新用户的sessionId存入redis,方便被下一个用户踢

jedisConfiguration.getJedisClient().set(phone + "redis", sessionId);

这里是总代码,至于redis什么的,相信你们都会的。

 public ChariotResponseEntity<UserVO> login(String phone, String password,HttpServletRequest request,HttpServletResponse response) throws Exception {
        logger.info("POST请求登录");

        if (StringUtils.isBlank(phone) || StringUtils.isBlank(password)) {
            return new ChariotResponseEntity<>(ChariotHttpStatus.USER_PARAMETER_ERROR);
        }
        Subject user = SecurityUtils.getSubject();

        UsernamePasswordToken token = new UsernamePasswordToken(phone, MD5Utils.getMD5Str(password).toCharArray());  //DigestUtils.md5Hex(password).toCharArray());//
        token.setRememberMe(true);
        try {
            user.login(token);
            user.getSession().setTimeout(-1000L); // 开发时设置永不过期,上线时需要调整 todo

        } catch (UnknownAccountException e) {
            logger.error("账号不存在:{}", e);
            return new ChariotResponseEntity<>(ChariotHttpStatus.USER_ACCOUNT_OR_PASSWORD_ERROR);
        } catch (DisabledAccountException e) {
            logger.error("账号未启用:{}", e);
            return new ChariotResponseEntity<>(ChariotHttpStatus.USER_NOT_ENABLED);
        } catch (IncorrectCredentialsException e) {
            logger.error("密码错误:{}", e);
            return new ChariotResponseEntity<>(ChariotHttpStatus.USER_ACCOUNT_OR_PASSWORD_ERROR);
        } catch (RuntimeException e) {
            logger.error("未知错误,请联系管理员:{}" + e.toString(), e);
            System.out.println(e.toString());
            return new ChariotResponseEntity<>(ChariotHttpStatus.USER_OTHER_REASON);
        }

        SessionsSecurityManager securityManager = (SessionsSecurityManager) SecurityUtils.getSecurityManager();

        DefaultSessionManager sessionManager = (DefaultSessionManager) securityManager.getSessionManager();

        String sessionId = String.valueOf(user.getSession().getId());

        String sessionId2 = jedisConfiguration.getJedisClient().get(phone+"redis");

        if(StringUtil.isNotEmpty(sessionId2)) {

            SessionKey sessionKey = new WebSessionKey(jedisConfiguration.getJedisClient().get(phone+"redis"),request,response);
            try {
                Session session = securityManager.getSession(sessionKey);
                if(!sessionId.equals(sessionId2))
                    sessionManager.getSessionDAO().delete(session);
            }catch (Exception e){
                e.printStackTrace();
             }

            Long result = jedisConfiguration.getJedisClient().del(phone+"redis");

        }

        String result1 = jedisConfiguration.getJedisClient().set(phone + "redis", sessionId);

        UserVO retUser = userService.getUserById(getCurrentUserId());

        return new ChariotResponseEntity<>(retUser, ChariotHttpStatus.OK);
    }

如果以上代码看着头痛,可以看我截取的部分

SessionsSecurityManager securityManager = (SessionsSecurityManager) SecurityUtils.getSecurityManager();

        DefaultSessionManager sessionManager = (DefaultSessionManager) securityManager.getSessionManager();

        String sessionId = String.valueOf(user.getSession().getId());

        String sessionId2 = jedisConfiguration.getJedisClient().get(phone+"redis");

        if(StringUtil.isNotEmpty(sessionId2)) {

            SessionKey sessionKey = new WebSessionKey(jedisConfiguration.getJedisClient().get(phone+"redis"),request,response);
            try {
                Session session = securityManager.getSession(sessionKey);
                if(!sessionId.equals(sessionId2))
                    sessionManager.getSessionDAO().delete(session);
            }catch (Exception e){
                e.printStackTrace();
             }

            Long result = jedisConfiguration.getJedisClient().del(phone+"redis");

        }

        String result1 = jedisConfiguration.getJedisClient().set(phone + "redis", sessionId);

个人感觉,我这样写的好处是准确的取到session,不用遍历,因为我在网上只看到过遍历出来取到的session,因为是自己的想法,所以,我认为自己是原创了,毕竟我也没找到其他人这么做的。


  • 0
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
实现用户长时间不操作就退出登录的方法可以通过以下步骤来实现: 1. 获取用户的最后一次操作时间,可以通过记录用户最后一次操作时间戳或者会话的最后访问时间来实现。 2. 设置一个时间阈值,比如说30分钟,如果当前时间减去用户最后一次操作时间大于等于这个时间阈值,则认为用户长时间没有操作,需要退出登录。 3. 在用户每次操作时,更新用户的最后一次操作时间。 4. 可以使用定时器或者线程来实现定时检查用户的最后一次操作时间,如果超过时间阈值则强制退出登录。 下面是一个 Java 实现的示例代码: ```java import java.util.Date; import java.util.Timer; import java.util.TimerTask; public class UserSession { private long lastAccessTime; private Timer timer; public UserSession() { lastAccessTime = new Date().getTime(); timer = new Timer(); timer.schedule(new TimeoutTask(), 30*60*1000); // 设置30分钟的超时时间 } public void access() { lastAccessTime = new Date().getTime(); } public void cancel() { timer.cancel(); } class TimeoutTask extends TimerTask { @Override public void run() { long currentTime = new Date().getTime(); if (currentTime - lastAccessTime >= 30*60*1000) { // 如果超时则退出登录 cancel(); // 执行退出登录操作 } } } } ``` 在每次用户访问时,调用 `access()` 方法更新最后一次访问时间,在用户退出登录时,调用 `cancel()` 方法取消定时器任务。当超时时,定时器任务会自动执行 `run()` 方法,检查最后一次访问时间是否超过指定的阈值,如果超过则执行退出登录操作

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值