使用框架: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 ChariotResponseEntitylogin(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,因为是自己的想法,所以,我认为自己是原创了,毕竟我也没找到其他人这么做的。

java 实现异地登陆_Java实现用户异地登陆踢人操作相关推荐

  1. java在线客服_java 网站用户在线和客服聊天

    这是应用到项目中的一个例子. 实现原理是将信息存储到Application域里面.然后使用Struts2 Action 用json格式的数据进行前后台交互. 截图: 前台用户界面: 后台客服界面: 编 ...

  2. java实现自动登录_java实现用户自动登录

    自动登录,是为了帮助用户多次使用这个网页时,不用再次输入用户名和密码就可以登录. 自动登录是指用户将用户的登录信息,人,保存到本地的文件中Cookie中. Name,value -声明时 new Co ...

  3. java中修改密码_java中用户密码加密时增加和修改的代码

    建一个MD5.java类 package util; /************************************************ MD5 算法的Java Bean Last M ...

  4. java swing 等待框_java – 让用户使用Swing等待

    我想让用户等待一段时间(10秒).我知道在JSP或servlet中我们使用META标记< META HTTP-EQUIV ="Refresh"CONTENT ="3 ...

  5. java模拟点击_java 模拟用户点击事件

    展开全部 调用按62616964757a686964616fe59b9ee7ad9431333365656630钮的 doClick() 方法,下例演示了 button2 模拟点击 button1 按 ...

  6. java stream 分组求和_Java stream List 求和、分组操作

    Java stream List 求和.分组操作 前言 项目中经常会使用Stream操作一些集合数据,今天记录一下我经常使用的Stream操作 求和操作public static void main( ...

  7. JAVA编程TXT文件_java开发之读写txt文件操作的实现

    项目结构: 运行效果: ======================================================== 下面是代码部分: ====================== ...

  8. java list 删除 遍历_Java list利用遍历进行删除操作3种方法解析

    Java list利用遍历进行删除操作3种方法解析 这篇文章主要介绍了Java list利用遍历进行删除操作3种方法解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需 ...

  9. java web定义数组_Java基础之数组--数组常用操作

    3.2一维数组 3.2.1声明数组 数组类型[] 数组名称:int[] username; 或者 数组类型 数组名称[];int username[]; 3.2.2初始化一维数组 一维数组初始化有两种 ...

最新文章

  1. MATLAB实时标定
  2. Matlab R2010在centost下的安装
  3. 组态王与c语言混合编程6,亚控 组态王嵌入版6.1
  4. 蓝桥杯-矩阵相乘(java)
  5. springboot的yml配置文件绑定时必须和相应的类中的属性类型对应,不然启动报错
  6. 300小时成为java程序员_直击面试现场: Java程序员3轮6小时面试, 成功拿到阿里offer!...
  7. python去重计数_用Python实现透视表的value_sum和countdistinct功能
  8. Auto CAD 2020 2019 2018 2017 2016 2015 2014 2013 2012 2011 2010 全版本 附带安装教程+入门到精通视频教程
  9. 深度解析脑机接口技术的现状与未来!
  10. 【Qt】绘制CIE色度图
  11. Java将数字金额转换为中文大写
  12. cad直线和圆弧倒角不相切_数控加工中心如何使用任意角度倒角C和倒圆角R功能的编程...
  13. git如何查看缓存区文件内容_[暂存盘已满怎么解决]git暂存区的理解
  14. RuntimeError: DataLoader worker (pid 4499) is killed by signal: Segmentation fault.检查内存条!
  15. OpenCv阈值化处理cv2.threshold()函数
  16. USYD悉尼大学DATA 2002 【R语言学习1】【介绍R】Introduction to R「虽迟但到」
  17. Excel按相同列内容合并表
  18. 机器学习之提升方法Adaboost算法
  19. redis incr命令最大值问题
  20. java 集合封装树形结构

热门文章

  1. 视频H5页面/视频app怎么做?
  2. 叁拾伍- Django Websocket 绝望之旅(dwebsocket 以及 channels)
  3. 乐乐音乐播放器 欢迎页面(二)
  4. NAIPC2018-K-Zoning Houses
  5. 重磅来袭!怎么用java编写app软件
  6. ajax高级程序设计_javascript高级程序设计核心知识总结
  7. 苹果8.1系统无服务器,iOS9强制降级iOS8教程
  8. 【Python】获取数组中非零元素
  9. WPFLoading遮层罩
  10. Boardcast Receiver 源码分析:广播的动态注册、发送和接收过程