有时候需要显示当前在线人数、当前在线用户,有时候可能需要强制某个用户下线等;此时就需要获取相应的在线用户并进行一些操作。

本章基于《第十六章 综合实例》代码构建。

会话控制器

Java代码  
  1. @RequiresPermissions("session:*")
  2. @Controller
  3. @RequestMapping("/sessions")
  4. public class SessionController {
  5. @Autowired
  6. private SessionDAO sessionDAO;
  7. @RequestMapping()
  8. public String list(Model model) {
  9. Collection<Session> sessions =  sessionDAO.getActiveSessions();
  10. model.addAttribute("sessions", sessions);
  11. model.addAttribute("sesessionCount", sessions.size());
  12. return "sessions/list";
  13. }
  14. @RequestMapping("/{sessionId}/forceLogout")
  15. public String forceLogout(@PathVariable("sessionId") String sessionId,
  16. RedirectAttributes redirectAttributes) {
  17. try {
  18. Session session = sessionDAO.readSession(sessionId);
  19. if(session != null) {
  20. session.setAttribute(
  21. Constants.SESSION_FORCE_LOGOUT_KEY, Boolean.TRUE);
  22. }
  23. } catch (Exception e) {/*ignore*/}
  24. redirectAttributes.addFlashAttribute("msg", "强制退出成功!");
  25. return "redirect:/sessions";
  26. }
  27. }

1、list方法:提供了展示所有在线会话列表,通过sessionDAO.getActiveSessions()获取所有在线的会话。

2、forceLogout方法:强制退出某一个会话,此处只在指定会话中设置Constants.SESSION_FORCE_LOGOUT_KEY属性,之后通过ForceLogoutFilter判断并进行强制退出。

此处展示会话列表的缺点是:sessionDAO.getActiveSessions()提供了获取所有活跃会话集合,如果做一般企业级应用问题不大,因为在线用户不多;但是如果应用的在线用户非常多,此种方法就不适合了,解决方案就是分页获取:

Java代码  
  1. Page<Session> getActiveSessions(int pageNumber, int pageSize);

Page对象除了包含pageNumber、pageSize属性之外,还包含totalSessions(总会话数)、Collection<Session> (当前页的会话)。

分页获取时,如果是MySQL这种关系数据库存储会话比较好办,如果使用Redis这种数据库可以考虑这样存储:

Java代码  
  1. session.id=会话序列化数据
  2. session.ids=会话id Set列表(接着可以使用LLEN获取长度,LRANGE分页获取)

会话创建时(如sessionId=123),那么redis命令如下所示:

Java代码  
  1. SET session.123 "Session序列化数据"
  2. LPUSH session.ids 123

会话删除时(如sessionId=123),那么redis命令如下所示:

Java代码  
  1. DEL session.123
  2. LREM session.ids 123

获取总活跃会话:

Java代码  
  1. LLEN session.ids

分页获取活跃会话:

Java代码  
  1. LRANGE key 0 10 #获取到会话ID
  2. MGET session.1 session.2……  #根据第一条命令获取的会话ID获取会话数据

ForceLogoutFilter

Java代码  
  1. public class ForceLogoutFilter extends AccessControlFilter {
  2. protected boolean isAccessAllowed(ServletRequest request, ServletResponse response, Object mappedValue) throws Exception {
  3. Session session = getSubject(request, response).getSession(false);
  4. if(session == null) {
  5. return true;
  6. }
  7. return session.getAttribute(Constants.SESSION_FORCE_LOGOUT_KEY) == null;
  8. }
  9. protected boolean onAccessDenied(ServletRequest request, ServletResponse response) throws Exception {
  10. try {
  11. getSubject(request, response).logout();//强制退出
  12. } catch (Exception e) {/*ignore exception*/}
  13. String loginUrl = getLoginUrl() + (getLoginUrl().contains("?") ? "&" : "?") + "forceLogout=1";
  14. WebUtils.issueRedirect(request, response, loginUrl);
  15. return false;
  16. }
  17. }

强制退出拦截器,如果用户会话中存在Constants.SESSION_FORCE_LOGOUT_KEY属性,表示被管理员强制退出了;然后调用Subject.logout()退出,且重定向到登录页面(自动拼上fourceLogout请求参数)。

登录控制器

在LoginController类的showLoginForm方法中最后添加如下代码:

Java代码  
  1. if(req.getParameter("forceLogout") != null) {
  2. model.addAttribute("error", "您已经被管理员强制退出,请重新登录");
  3. }

即如果有请求参数forceLogout表示是管理员强制退出的,在界面上显示相应的信息。

Shiro配置spring-config-shiro.xml

和之前的唯一区别是在shiroFilter中的filterChainDefinitions拦截器链定义中添加了forceLogout拦截器:

Java代码  
  1. /** = forceLogout,user,sysUser

测试

1、首先输入http://localhost:8080/chapter24/跳转到登录页面输入admin/123456登录;

2、登录成功后,点击菜单的“会话管理”,可以看到当前在线会话列表:

3、点击“强制退出”按钮,会话相应的用户再点击界面的话会看到如下界面,表示已经被强制退出了: 

另外可参考我的ES中的在线会话管理功能:UserOnlineController.java,其使用数据库存储会话,并分页获取在线会话。

转载于:https://www.cnblogs.com/guoziyi/p/7131261.html

Shiro学习(24)在线回话管理相关推荐

  1. shiro学习(24):Spring的transaction-manager的用法

    <?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.sp ...

  2. SpringBoot整合Shiro学习(上)

    SpringBoot整合Shiro(上) 基于[编程不良人]2020最新版Shiro教程,整合SpringBoot项目实战教程 哔哩哔哩链接:https://www.bilibili.com/vide ...

  3. 【毕业设计】基于微信小程序的在线学习平台 在线学习微信小程序

    如今的这个网络的时代,由于网络的不断发展,在线教育平台的兴起,大大改变了人们对于教育的重新认识,也改变了传统的教育方式,现在人们利用网络给人们带来更广阔的世界观,加大社会化的协同,知识也是越来越去中心 ...

  4. SpringBoot+Shiro学习(八):RememberMe

    这一章比较简单,就不多说了,上代码: /** * cookie对象; * rememberMeCookie()方法是设置Cookie的生成模版,比如cookie的name,cookie的有效时间等等. ...

  5. Shiro学习记录(详细)

    文章目录 Shiro学习记录 shiro核心组件 Spring Boot 整合 Shiro Shiro 整合 Thymeleaf Shiro学习记录 什么是 Shiro 官网:http://shiro ...

  6. linux软件包管理解析,linux学习笔记_09_软件包管理解析.doc

    linux学习笔记_09_软件包管理解析 软件包管理 软件包分类 源码包(C语言编写的源代码) linux主要由C语言来写. 源码包可以用写字板打开 脚本安装包:源码包进行再开发的源码包(提供安装界面 ...

  7. shiro学习笔记:remeberMe,多次登录锁死账号

    关于shiro的rememberme的实现,再之前我们是使用cookie实现的,这里也是一样,原理都是相同的: 不过因为用到了shiro框架,因此需要再shiro中配置cookie以及缓存等,以及管理 ...

  8. Notion Like 笔记软件使用教程·学习资源汇总·知识管理方案

    Notion Like 笔记软件使用教程·学习资源汇总·知识管理方案:深度评测.辅助工具.信息管理.时间管理.任务管理.思维管理.项目管理.文件管理.笔记方法.记忆方法.写作方法 关于 Notion ...

  9. Shiro学习笔记_02:shiro的认证+shiro的授权

    Shiro 学习笔记 本文基于B站UP主[编程不良人]视频教程[2020最新版Shiro教程,整合SpringBoot项目实战教程]进行整理记录,仅用于个人学习交流使用. 视频链接:https://w ...

最新文章

  1. Android Activity的onRestart()方法
  2. 定点c程序之五:定点数的字长效应
  3. php成品网站安装,PHPweb成品网站安装环境要求和安装方法
  4. PocketSphinx语音识别系统语言模型的训练和声学模型的改进
  5. mysql join 索引 无效_ORACLE MYSQL中join 字段类型不同索引失效的情况-阿里云开发者社区...
  6. 你在微信漂流瓶里遇到过哪些有意思的人和事?
  7. 吃完饭打嗝原因及治疗方法(分享)
  8. 制作中国范围地图的几点注意事项
  9. 深入理解Java类加载器(ClassLoader)
  10. 【韵律迁移】Robust and fine-grained prosody control of end-to-end speech synthesis
  11. python12306买票_Python 使用 selenium 实现半自动购买12306火车票
  12. xp升级win7_微软正式停止支持Win7,部分用户拒绝升级系统,原因令人信服
  13. Hi3861网络通信——UDP收发
  14. visual studio code远程连接服务器
  15. 芯片厂家GitHub库
  16. Hbase数据库的常用操作命令
  17. 图像、图形、图片文件格式
  18. Java数组之一维数值数组之数据去重
  19. 模数转换,你必须知道的8个经典ADC转换电路方案
  20. wireshark不显示随身wifi热点问题的解决

热门文章

  1. 使用flash在IPAD2上播放FLV效率不高
  2. DTLS协议中的509证书和密钥如何传输
  3. asio 组播包ssdp
  4. python成绩统计_python统计考试成绩排名
  5. jQuery中append()、prepend()与after()、before()的区别
  6. 【Elasticsearch】Elasticsearch之别名
  7. 95-190-741-源码-WindowFunction-窗口流简介
  8. 在IDEA中安装使用Antlr
  9. 递归算法的总结与应用
  10. List 集合的常用方法