Shiro学习(24)在线回话管理

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

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

会话控制器

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

时间: 2024-10-14 06:28:32

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

第24章 在线会话管理

有时候需要显示当前在线人数.当前在线用户,有时候可能需要强制某个用户下线等,此时就需要获取相应的在线用户并进行一些操作,本章基于<第十六章 综合实例>代码构建. 会话控制器 @RequiresPermissions("session:*") @Controller @RequestMapping("/sessions") public class SessionController { @Autowired private SessionDAO sess

Shiro学习(总结)

声明:本文原文地址:http://www.iteye.com/blogs/subjects/shiro 感谢开涛提供的博文,让我学到了很多,在这里由衷的感谢你,同时我强烈的推荐开涛的博文,他的博文力争完美,讲解细致,是基于实际的项目进行讲解,有理有据值得学习和借鉴.同时,在这里自荐一下,也希望大家也能够多多的关注我的博文,希望你的技术有所提高,大家共同学习共同进步. 下面是开涛整理的Shiro的目录,供大家学习. Shiro目录 第一章  Shiro简介 第二章  身份验证 第三章  授权 第四

shiro学习第一步

? 初来乍到 shiro是Java的一个安全框架,如果在实际工作中我们并不太需要特别复杂的东西,那么我们可以选用shiro,而不用spring Security; Shiro 可以非常容易的开发出实用的应用,可以帮助我们完成认证.授权.加密.回话管理.与Web集成,缓存等:基本功能点如下: Authentication:身份认证/登录,验证用户是不是拥有相应的身份: Authorization:授权,即权限验证,验证某个已认证的用户是否拥有某个权限:即判断用户是否能做事情,常见的如:验证某个用户

Ajax学习教程在线阅读

  1.什么是AJAX ?(1) 2.什么是AJAX ?(2) 3.什么是AJAX ?(3) 4.什么是AJAX ?(4) 5.Ajax基础教程(1)-Ajax简介 1.1 Web应用简史 6.Ajax基础教程(1)-Ajax简介 1.2 浏览器历史 7.Ajax基础教程(1)-Ajax简介 1.3 Web应用的发展历程 8.Ajax基础教程(1)-Ajax简介 1.3 Web应用的发展历程(2) 9.Ajax基础教程(1)-Ajax简介 1.3 Web应用的发展历程(3) 10.Ajax基础教

Object C学习笔记25-文件管理(一)

在此篇文章中简单记录一下文件管理,在Object C中NSFileManager用于管理文件已经路径.在Object C中的文件路径可以是相对路径也可以是绝对路径.斜线"/"开头,斜线实际上就是一个目录,称为 根目录.字符(-)用作用户主目录的缩写.点" . "表示当前目录,两点"  .. "表示父目录. 一. 创建NSFileManager 对象 NSFileManager非常简单,可以使用如下方式来创建NSFileManager对象. NSS

Shiro学习(20)无状态Web应用集成

在一些环境中,可能需要把Web应用做成无状态的,即服务器端无状态,就是说服务器端不会存储像会话这种东西,而是每次请求时带上相应的用户名进行登录.如一些REST风格的API,如果不使用OAuth2协议,就可以使用如REST+HMAC认证进行访问.HMAC(Hash-based Message Authentication Code):基于散列的消息认证码,使用一个密钥和一个消息作为输入,生成它们的消息摘要.注意该密钥只有客户端和服务端知道,其他第三方是不知道的.访问时使用该消息摘要进行传播,服务端

在线会话管理

有时候需要显示当前在线人数.当前在线用户,有时候可能需要强制某个用户下线等:此时就需要获取相应的在线用户并进行一些操作. 会话控制器 @RequiresPermissions("session:*") @Controller @RequestMapping("/sessions") public class SessionController { @Autowired private SessionDAO sessionDAO; @RequestMapping()

redis学习教程四《管理、备份、客户端连接》

redis学习教程四<管理.备份.客户端连接> 一:Redis服务器命令 Redis服务器命令 下表列出了与Redis服务器相关的一些基本命令. 序号 命令 说明 1 BGREWRITEAOF 异步重写仅追加的文件 2 BGSAVE 将数据集异步保存到磁盘 3 CLIENT KILL [ip:port] [ID client-id] 杀死或断开指定的客户端的连接 4 CLIENT LIST 获取到服务器的客户端连接列表 5 CLIENT GETNAME 获取当前连接的名称 6 CLIENT P

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

前言 如果你了解 Apache Flink 的话,那么你应该熟悉该如何像 Flink 发送数据或者如何从 Flink 获取数据.但是在某些情况下,我们需要将配置数据发送到 Flink 集群并从中接收一些额外的数据. 在本文的第一部分中,我将描述如何将配置数据发送到 Flink 集群.我们需要配置很多东西:方法参数.配置文件.机器学习模型.Flink 提供了几种不同的方法,我们将介绍如何使用它们以及何时使用它们.在本文的第二部分中,我将描述如何从 Flink 集群中获取数据. 如何发送数据给 Ta