Shiro学习(24)在线回话管理
有时候需要显示当前在线人数、当前在线用户,有时候可能需要强制某个用户下线等;此时就需要获取相应的在线用户并进行一些操作。
本章基于《第十六章 综合实例》代码构建。
会话控制器
- @RequiresPermissions("session:*")
- @Controller
- @RequestMapping("/sessions")
- public class SessionController {
- @Autowired
- private SessionDAO sessionDAO;
- @RequestMapping()
- public String list(Model model) {
- Collection<Session> sessions = sessionDAO.getActiveSessions();
- model.addAttribute("sessions", sessions);
- model.addAttribute("sesessionCount", sessions.size());
- return "sessions/list";
- }
- @RequestMapping("/{sessionId}/forceLogout")
- public String forceLogout(@PathVariable("sessionId") String sessionId,
- RedirectAttributes redirectAttributes) {
- try {
- Session session = sessionDAO.readSession(sessionId);
- if(session != null) {
- session.setAttribute(
- Constants.SESSION_FORCE_LOGOUT_KEY, Boolean.TRUE);
- }
- } catch (Exception e) {/*ignore*/}
- redirectAttributes.addFlashAttribute("msg", "强制退出成功!");
- return "redirect:/sessions";
- }
- }
1、list方法:提供了展示所有在线会话列表,通过sessionDAO.getActiveSessions()获取所有在线的会话。
2、forceLogout方法:强制退出某一个会话,此处只在指定会话中设置Constants.SESSION_FORCE_LOGOUT_KEY属性,之后通过ForceLogoutFilter判断并进行强制退出。
此处展示会话列表的缺点是:sessionDAO.getActiveSessions()提供了获取所有活跃会话集合,如果做一般企业级应用问题不大,因为在线用户不多;但是如果应用的在线用户非常多,此种方法就不适合了,解决方案就是分页获取:
- Page<Session> getActiveSessions(int pageNumber, int pageSize);
Page对象除了包含pageNumber、pageSize属性之外,还包含totalSessions(总会话数)、Collection<Session> (当前页的会话)。
分页获取时,如果是MySQL这种关系数据库存储会话比较好办,如果使用Redis这种数据库可以考虑这样存储:
- session.id=会话序列化数据
- session.ids=会话id Set列表(接着可以使用LLEN获取长度,LRANGE分页获取)
会话创建时(如sessionId=123),那么redis命令如下所示:
- SET session.123 "Session序列化数据"
- LPUSH session.ids 123
会话删除时(如sessionId=123),那么redis命令如下所示:
- DEL session.123
- LREM session.ids 123
获取总活跃会话:
- LLEN session.ids
分页获取活跃会话:
- LRANGE key 0 10 #获取到会话ID
- MGET session.1 session.2…… #根据第一条命令获取的会话ID获取会话数据
ForceLogoutFilter
- public class ForceLogoutFilter extends AccessControlFilter {
- protected boolean isAccessAllowed(ServletRequest request, ServletResponse response, Object mappedValue) throws Exception {
- Session session = getSubject(request, response).getSession(false);
- if(session == null) {
- return true;
- }
- return session.getAttribute(Constants.SESSION_FORCE_LOGOUT_KEY) == null;
- }
- protected boolean onAccessDenied(ServletRequest request, ServletResponse response) throws Exception {
- try {
- getSubject(request, response).logout();//强制退出
- } catch (Exception e) {/*ignore exception*/}
- String loginUrl = getLoginUrl() + (getLoginUrl().contains("?") ? "&" : "?") + "forceLogout=1";
- WebUtils.issueRedirect(request, response, loginUrl);
- return false;
- }
- }
强制退出拦截器,如果用户会话中存在Constants.SESSION_FORCE_LOGOUT_KEY属性,表示被管理员强制退出了;然后调用Subject.logout()退出,且重定向到登录页面(自动拼上fourceLogout请求参数)。
登录控制器
在LoginController类的showLoginForm方法中最后添加如下代码:
- if(req.getParameter("forceLogout") != null) {
- model.addAttribute("error", "您已经被管理员强制退出,请重新登录");
- }
即如果有请求参数forceLogout表示是管理员强制退出的,在界面上显示相应的信息。
Shiro配置spring-config-shiro.xml
和之前的唯一区别是在shiroFilter中的filterChainDefinitions拦截器链定义中添加了forceLogout拦截器:
- /** = forceLogout,user,sysUser
1、首先输入http://localhost:8080/chapter24/跳转到登录页面输入admin/123456登录;
2、登录成功后,点击菜单的“会话管理”,可以看到当前在线会话列表:
3、点击“强制退出”按钮,会话相应的用户再点击界面的话会看到如下界面,表示已经被强制退出了:
另外可参考我的ES中的在线会话管理功能:UserOnlineController.java,其使用数据库存储会话,并分页获取在线会话。
Shiro学习(24)在线回话管理的更多相关文章
- Apache shiro学习总结
Apache shiro集群实现 (一) shiro入门介绍 Apache shiro集群实现 (二) shiro 的INI配置 Apache shiro集群实现 (三)shiro身份认证(Shiro ...
- 第二十四章 在线会话管理——《跟我学Shiro》
目录贴:跟我学Shiro目录贴 有时候需要显示当前在线人数.当前在线用户,有时候可能需要强制某个用户下线等:此时就需要获取相应的在线用户并进行一些操作. 本章基于<第十六章 综合实例>代码 ...
- SpringBoot+Shiro学习(七):Filter过滤器管理
SpringBoot+Shiro学习(七):Filter过滤器管理 Hiwayz 关注 0.5 2018.09.06 19:09* 字数 1070 阅读 5922评论 1喜欢 20 先从我们写的一个 ...
- Apache Shiro学习-2-Apache Shiro Web Support
Apache Shiro Web Support 1. 配置 将 Shiro 整合到 Web 应用中的最简单方式是在 web.xml 的 Servlet ContextListener 和 Fil ...
- Shiro学习(总结)
声明:本文原文地址:http://www.iteye.com/blogs/subjects/shiro 感谢开涛提供的博文,让我学到了非常多.在这里由衷的感谢你,同一时候我强烈的推荐开涛的博文.他的博 ...
- 蓝牙芯片NRF51822入门学习1:时间管理
前言 之前辞职找工作的时候发现,很多公司希望招聘蓝牙技术方面的人才,所以干脆丢开LWIP静下心来学习蓝牙技术.原本以为一两星期能基本学会的,谁知道所选的蓝牙芯片nrf51822是个坑货,坑了我一个月. ...
- (转)Shiro学习
(二期)13.权限框架shiro讲解 [课程13]自定义Realm.xmind36.8KB [课程13]用户授权流程.xmind0.2MB [课程13]shiro简介.xmind0.3MB [课程13 ...
- 基于SpringCloud的Microservices架构实战案例-在线API管理
simplemall项目前几篇回顾: 1基于SpringCloud的Microservices架构实战案例-序篇 2基于SpringCloud的Microservices架构实战案例-架构拆解 3基于 ...
- Flink 从0到1学习 —— Flink 中如何管理配置?
前言 如果你了解 Apache Flink 的话,那么你应该熟悉该如何像 Flink 发送数据或者如何从 Flink 获取数据.但是在某些情况下,我们需要将配置数据发送到 Flink 集群并从中接收一 ...
随机推荐
- 【leetcode】1003. Check If Word Is Valid After Substitutions
题目如下: We are given that the string "abc" is valid. From any valid string V, we may split V ...
- Vue学习笔记【29】——Vue路由(命名视图实现经典布局)
命名视图实现经典布局 标签代码结构: <div id="app"> <router-view></router-view> < ...
- Oracle with as语法
with as优点 增加了sql的易读性,如果构造了多个子查询,结构会更清晰: 更重要的是:“一次分析,多次使用”,这也是为什么会提供性能的地方,达到了“少读”的目标 用法:给查询的语句起个别名 e. ...
- php wordwrap()函数 语法
php wordwrap()函数 语法 wordwrap()函数怎么用? wordwrap()函数表示按照指定长度对字符串进行折行处理,语法是wordwrap(string,width,break,c ...
- UNP学习第五章
一.概述 想要写一个完整的TCP客户-服务器程序例子,有下面功能的回射服务器 1.客户从标准输入读一行文本,写到服务器上: 2.服务器从网络输入读此行,并回射给客户: 3.客户读此回射行并写到标准输出 ...
- ubuntu Linux下chromium无法使用flash解决方法
Chromium作为谷歌的开源浏览器将不再支持Netscape浏览器插件API,Adobe公司的Flash将无法正常工作了.然而用户可以使用Pepper Flash Player,这是谷歌浏览器上一款 ...
- <Jmeter入门不放弃>之<1.认识jmeter>
大家这里参考学习的时候,我就不在这里配截图了,因为需要你打开工具根据文档自己去找,,才有印象,大家一定要启动JMeter! 一.Jmeter是什么 由 Apache 组织开发,基于JAVA压力测试工具 ...
- angularjs &登录跳转
如果要使用$location,$stateParams,那么必须有相应形参controller: function ($rootScope, $http, $scope, $state,$locati ...
- 使用函数指针模拟C++多态
#include <iostream> using namespace std; class Base { public : void display() { cout << ...
- jQuery.Deferred exception: a.indexOf is not a function TypeError: a.indexOf is not a function
jq版本问题 3.2换成1.9就可以了