`
jinnianshilongnian
  • 浏览: 21504075 次
  • 性别: Icon_minigender_1
博客专栏
5c8dac6a-21dc-3466-8abb-057664ab39c7
跟我学spring3
浏览量:2418686
D659df3e-4ad7-3b12-8b9a-1e94abd75ac3
Spring杂谈
浏览量:3008790
43989fe4-8b6b-3109-aaec-379d27dd4090
跟开涛学SpringMVC...
浏览量:5639490
1df97887-a9e1-3328-b6da-091f51f886a1
Servlet3.1规范翻...
浏览量:259916
4f347843-a078-36c1-977f-797c7fc123fc
springmvc杂谈
浏览量:1597323
22722232-95c1-34f2-b8e1-d059493d3d98
hibernate杂谈
浏览量:250220
45b32b6f-7468-3077-be40-00a5853c9a48
跟我学Shiro
浏览量:5858959
Group-logo
跟我学Nginx+Lua开...
浏览量:702008
5041f67a-12b2-30ba-814d-b55f466529d5
亿级流量网站架构核心技术
浏览量:785224
社区版块
存档分类
最新评论

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

阅读更多

 

目录贴: 跟我学Shiro目录贴

 

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

 

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

 

会话控制器

@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";
    }
} 

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

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

 

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

Page<Session> getActiveSessions(int pageNumber, int pageSize);

Page对象除了包含pageNumberpageSize属性之外,还包含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,其使用数据库存储会话,并分页获取在线会话。

 

        

 

 

示例源代码:https://github.com/zhangkaitao/shiro-example;可加群 231889722 探讨Spring/Shiro技术。

        

  

11
3
分享到:
评论
11 楼 sjzcmlt 2018-08-22  
t哥,已经读完,想要跪地膜拜
10 楼 流不驻的记忆 2018-05-08  
       
9 楼 Aries穆 2016-07-01  
为什么我的sessionDAO.getActiveSessions为空呢
8 楼 ruiliang1988 2016-03-29  
这里写错了?你妺,又在忽悠我。
session.ids=会话id Set列表(接着可以使用LLEN获取长度,LRANGE分页获取)  

你这是list列表的命令啊,set是集合,

这里用list还有一个不足,我记得list是不能判断元素是否存在
7 楼 bill1 2015-10-28  
请教一个问题,如果用户没有退出,只有浏览器关闭了,为什么session中还是有用户啊?
6 楼 酒意hn 2015-09-22  
为啥登陆控制器是这样的呢
@RequestMapping(value = "/login"    )
    public String showLoginForm(HttpServletRequest req, Model model) {
        String exceptionClassName = (String)req.getAttribute("shiroLoginFailure");
        System.out.println("exceptionClassName="+exceptionClassName);
        String error = null;
        if(UnknownAccountException.class.getName().equals(exceptionClassName)) {
            error = "用户名/密码错误1";
        } else if(IncorrectCredentialsException.class.getName().equals(exceptionClassName)) {
            error = "用户名/密码错误2";
        } else if(exceptionClassName != null) {
            error = "其他错误:" + exceptionClassName;
        }
        model.addAttribute("error", error);
        if(req.getParameter("forceLogout") != null) {
            model.addAttribute("error", "您已经被管理员强制退出,请重新登录");
        }
        return "login";
    }
这岂不是一直都是错误,永远登不上去吗。。。
5 楼 liuwenjie517333 2015-06-30  
一直想写篇文章。文章的名字就叫一次“http登录”,所发生的故事。把登录相关的安全性东西:比如通信安全用的https,防机器登录的验证码技术,密码在后台的加密存储,加密比较,登录失败策越等全部写出来。开涛能开篇文章介绍下登录业务不,随着知识的认识加深,感觉要做好登录业务,也不是件简单的事。
4 楼 liuwenjie517333 2015-06-30  
一直想写篇文章。文章的名字就叫一次“http登录”,所发生的故事。把登录相关的安全性东西:比如通信安全用的https,防机器登录的验证码技术,密码在后台的加密存储,加密比较,登录失败策越等全部写出来。涛+哥能开篇文章介绍下登录业务不,随着知识的认识加深,感觉要做好登录业务,也不是件简单的事。
3 楼 liuwenjie517333 2015-06-30  
一直想写篇文章。文章的名字就叫一次“http登录”,所发生的故事。把登录相关的安全性东西:比如通信安全用的https,防机器登录的验证码技术,密码在后台的加密存储,加密比较,登录失败策越等全部写出来。涛 哥能开篇文章介绍下登录业务不,随着知识的认识加深,感觉要做好登录业务,也不是件简单的事。
2 楼 560130911 2014-04-21  
560130911 写道
存在一个问题呢,如果同时使用并发人数控制功能,在线人数统计将会出现问题,即踢出的人的session还存在,但是取不到用户登入信息

没有问题了,是我搞错了
1 楼 560130911 2014-04-21  
存在一个问题呢,如果同时使用并发人数控制功能,在线人数统计将会出现问题,即踢出的人的session还存在,但是取不到用户登入信息

相关推荐

    第十七章 OAuth2集成——《跟我学Shiro》 - 开涛的博客 - ITeye技术网站2

    在《跟我学Shiro》的第十七章中,作者开涛介绍了如何集成OAuth2,使用Apache Oltu作为OAuth2服务端的实现。实现中涉及以下关键部分: 1. **依赖**:引入了`authzserver`(授权服务器依赖)和`resourceserver`(资源...

    [资料][Java]跟我学Shiro教程_Java跟我学Shiro教程_shiro_

    Apache Shiro 是一个强大且易用的 Java 安全框架,提供了认证、授权、加密和会话管理功能,可以非常方便地开发出足够安全的应用。...阅读 "[资料][Java]跟我学Shiro教程.pdf",你将得到更详细的步骤指导和实践案例。

    跟我一起学shiro 张开涛

    《跟我一起学Shiro——张开涛》这本书是针对初学者的优秀教程,旨在帮助读者快速理解和掌握Shiro的基本用法和核心概念。 **1. Shiro基础** Shiro的基础概念包括Subject、Realms、Cryptography和Session。Subject是...

    跟我学Shiro

    通过《跟我学Shiro》.pdf,你将学习到如何创建 Realm 实现数据源连接、配置 Shiro 安全框架、处理登录和登出逻辑、实现权限控制以及在实际项目中部署和调优 Shiro。 10. **最佳实践** 学习 Shiro 的过程中,了解...

    跟我学Shiro教程.rar

    "跟我学Shiro教程"这个资源显然是为了帮助学习者深入理解并掌握Shiro的核心概念和实际应用。 在Shiro的认证服务中,其主要目标是确认用户身份。这通常涉及用户登录过程,其中用户提供的凭证(如用户名和密码)被...

    跟我学Shiro教程及其课程分章节源码

    Apache Shiro是一个强大易用的Java安全框架,...我找了一版 跟我学Shiro教程PDF,里面讲的很详细.里面还附带了每个章节的源码.值得你收藏哟!饮水思源——原文出自:http://jinnianshilongnian.iteye.com/blog/2049092

    跟我学Shiro-java开发+spring开发

    《跟我学Shiro-java开发+spring开发》是一个深入学习Java安全框架Shiro和Spring集成的教程,旨在帮助开发者掌握这两个关键技术在实际项目中的应用。Shiro是一个强大的且易用的Java安全框架,提供了认证、授权、加密...

    跟我学shiro

    #### 十四、SSL - **概念**:使用 SSL 加密通信,保护数据安全。 #### 十五、单点登录 - **概念**:用户只需一次登录就可以访问所有相关系统。 - **实现**: - **服务器端**:实现 SSO 的核心逻辑。 - **客户端**...

    shiro教程 跟我学Shiro教程

    "跟我学Shiro教程"资源包包含了全面学习Shiro所需的重要材料,包括文档和实践示例。 首先,我们来看《Apache_Shiro参考手册中文版.pdf》。这本书籍详细介绍了Shiro框架的各个组件和使用方法。通过阅读,你可以了解...

    《跟我学Shiro》- 张开涛.txt

    ***txt文件中含有下载地址** 《跟我学Shiro》- 张开涛,PDF版本,带目录,清晰。 示例源代码:https://github.com/zhangkaitao/shiro-example; 加qun 231889722 探讨Spring/Shiro技术。

    跟我学Shiro第11章Demo

    在"跟我学Shiro第11章Demo"中,我们将深入探讨Shiro的核心组件,特别是其在缓存管理和会话管理中的应用。 首先,我们关注的是Cache缓存。Shiro支持缓存来提高性能,避免频繁的数据库查询。它允许开发者将敏感操作的...

    跟我学Shiro教程 pdf

    《跟我学Shiro》PDF完结版下载, Apache Shiro是Java的一个安全框架。目前,使用Apache Shiro的人越来越多,因为它相当简单,对比Spring Security,可能没有Spring Security做的功能强大,但是在实际工作时可能并不...

    跟我学shiro源代码

    "跟我学Shiro源代码"是一份针对Shiro框架的详细教程,通过这本书,读者能够深入理解Shiro的核心概念和用法,并通过实际的代码示例来提升自己的技能。 1. **身份验证(Authentication)**:Shiro提供了一套完善的...

    跟我学shiro文档及源码

    在《跟我学Shiro》这本书中,作者深入浅出地讲解了 Shiro 的核心概念与实际应用场景,配合源码分析,有助于读者更好地理解和掌握 Shiro 的工作原理。 1. **Shiro 概述** - Shiro 的设计目标是简化应用安全开发,它...

    跟我学Shiro源码

    "跟我学Shiro源码"这个主题旨在深入理解Shiro的工作原理,通过分析源码来提升我们对安全编程的认知。 1. **Shiro架构** Shiro 的核心组件包括 Realm(认证与授权信息源)、SecurityManager(安全管理器)、Subject...

    跟我学 Shiro - v1.1.rar

    Apache Shiro 是 Java 的一个安全框架。目前,使用 Apache Shiro 的人越来越多,因为它相当简单,对比 Sp ring Security,可能没有 Spring Security 做的功能强大,但是在实际工作时可能并不需要那么复杂的东西,所 ...

Global site tag (gtag.js) - Google Analytics