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

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

会话控制器

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,其使用数据库存储会话,并分页获取在线会话。

Shiro学习(24)在线回话管理的更多相关文章

  1. Apache shiro学习总结

    Apache shiro集群实现 (一) shiro入门介绍 Apache shiro集群实现 (二) shiro 的INI配置 Apache shiro集群实现 (三)shiro身份认证(Shiro ...

  2. 第二十四章 在线会话管理——《跟我学Shiro》

    目录贴:跟我学Shiro目录贴 有时候需要显示当前在线人数.当前在线用户,有时候可能需要强制某个用户下线等:此时就需要获取相应的在线用户并进行一些操作. 本章基于<第十六章 综合实例>代码 ...

  3. SpringBoot+Shiro学习(七):Filter过滤器管理

    SpringBoot+Shiro学习(七):Filter过滤器管理 Hiwayz 关注  0.5 2018.09.06 19:09* 字数 1070 阅读 5922评论 1喜欢 20 先从我们写的一个 ...

  4. Apache Shiro学习-2-Apache Shiro Web Support

     Apache Shiro Web Support  1. 配置 将 Shiro 整合到 Web 应用中的最简单方式是在 web.xml 的 Servlet ContextListener 和 Fil ...

  5. Shiro学习(总结)

    声明:本文原文地址:http://www.iteye.com/blogs/subjects/shiro 感谢开涛提供的博文,让我学到了非常多.在这里由衷的感谢你,同一时候我强烈的推荐开涛的博文.他的博 ...

  6. 蓝牙芯片NRF51822入门学习1:时间管理

    前言 之前辞职找工作的时候发现,很多公司希望招聘蓝牙技术方面的人才,所以干脆丢开LWIP静下心来学习蓝牙技术.原本以为一两星期能基本学会的,谁知道所选的蓝牙芯片nrf51822是个坑货,坑了我一个月. ...

  7. (转)Shiro学习

    (二期)13.权限框架shiro讲解 [课程13]自定义Realm.xmind36.8KB [课程13]用户授权流程.xmind0.2MB [课程13]shiro简介.xmind0.3MB [课程13 ...

  8. 基于SpringCloud的Microservices架构实战案例-在线API管理

    simplemall项目前几篇回顾: 1基于SpringCloud的Microservices架构实战案例-序篇 2基于SpringCloud的Microservices架构实战案例-架构拆解 3基于 ...

  9. Flink 从0到1学习 —— Flink 中如何管理配置?

    前言 如果你了解 Apache Flink 的话,那么你应该熟悉该如何像 Flink 发送数据或者如何从 Flink 获取数据.但是在某些情况下,我们需要将配置数据发送到 Flink 集群并从中接收一 ...

随机推荐

  1. [BOOKS]BIG DATA and DATA ANALYTICS: The Beginner's Guide to Understanding the Analytical World

  2. python--闭包函数、装饰器

    先来点补充. x= def foo(): print(x) x= foo() 结果: x= def foo(): global x x= print(x) foo() print(x) 结果: x= ...

  3. ELK Stack 7.1.1之集群搭建

    一. 环境准备:3台Linux服务器,系统为CentOS 7.5 角色划分:3台机器全部安装jdk1.8,全部安装elasticsearch (后续都简称为es集群) 主节点上需要安装kibana与l ...

  4. POJ 1151 线段树+扫描线(计算矩形面积并)

    前一篇博客有了讲解就不再叙述了 #include<cstdio> #include<cstring> #include<cmath> #include<ios ...

  5. springboot-redis相关配置整理

    1.pom.xml引入对应数据文件 <dependency> <groupId>org.springframework.boot</groupId> <art ...

  6. 2019ccpc秦皇岛/Gym102361 D - Decimal 签到

    题意: 给定n,判断1/n是否在十进制下无限循环 题解:判断n的是否包含除2,5以外的因数即可 #include<iostream> #include<cstdio> #inc ...

  7. MySQL-8.0填坑

    Client does not support authentication protocol 或 Authentication plugin 'caching_sha2_password' cann ...

  8. grep 后加单引号、双引号和不加引号的区别

    请尊重版权,原文地址:https://blog.csdn.net/cupidove/article/details/8783968 单引号: 可以说是所见即所得:即将单引号内的内容原样输出,或者描述为 ...

  9. OA集成备注

    1. 查看轨迹方法<script type="text/javascript"> function WinOpenIt(url) { //alert(1); var t ...

  10. activiti7流程变量的测试(设置全局变量)

    package com.zcc.activiti03; import org.activiti.engine.*;import org.activiti.engine.repository.Deplo ...