shiro会话监听_SpringBoot集成Shiro会话管理

在Shiro中我们可以通过org.apache.shiro.session.mgt.eis.SessionDAO对象的getActiveSessions()方法方便的获取到当前所有有效的Session对象。通过这些Session对象,我们可以实现一些比较有趣的功能,比如查看当前系统的在线人数,查看这些在线用户的一些基本信息,强制让某个用户下线等。

我们在现有的Spring Boot Shiro项目基础上进行一些改造。

Redis Session管理

Redis作为缓存实现,那么SessionDAO为RedisSessionDAO:

/**

* session会话

*

* @return

*/

@Bean

public RedisSessionDAO sessionDAO() {

RedisSessionDAO redisSessionDAO = new RedisSessionDAO();

redisSessionDAO.setRedisManager(redisManager());

return redisSessionDAO;

}

Ehcache Session管理

Ehcache作为缓存实现,那么SessionDAO为RedisSessionDAO:

/**

* session会话

*

* @return

*/

@Bean

public SessionDAO sessionDAO() {

MemorySessionDAO sessionDAO = new MemorySessionDAO();

return sessionDAO;

}

SessionManager 管理器

SessionDao通过org.apache.shiro.session.mgt.SessionManager进行管理,在ShiroConfig中配置SessionManager:

/**

* session会话管理器

*/

@Bean

public SessionManager sessionManager() {

DefaultWebSessionManager sessionManager = new DefaultWebSessionManager();

Collection listeners = new ArrayList<>();

listeners.add(new ShiroSessionListener());

sessionManager.setSessionListeners(listeners);

sessionManager.setSessionDAO(sessionDAO());

return sessionManager;

}

ShiroSessionListener 监听器

public class ShiroSessionListener implements SessionListener{

private final AtomicInteger sessionCount = new AtomicInteger(0);

@Override

public void onStart(Session session) {

sessionCount.incrementAndGet();

}

@Override

public void onStop(Session session) {

sessionCount.decrementAndGet();

}

@Override

public void onExpiration(Session session) {

sessionCount.decrementAndGet();

}

}



ShiroSessionListener维护着一个原子类型的Integer对象,用于统计在线Session的数量。

定义完SessionManager后,还需将其注入到SecurityManager中:

@Bean

public SecurityManager securityManager(){

DefaultWebSecurityManager securityManager = new DefaultWebSecurityManager();

securityManager.setRealm(shiroRealm());

...

securityManager.setSessionManager(sessionManager());

return securityManager;

}

UserOnline

配置完ShiroConfig后,我们可以创建一个UserOnline实体类,用于描述每个在线用户的基本信息:

public class UserOnline implements Serializable{

private static final long serialVersionUID = 3828664348416633856L;

// session id

private String id;

// 用户id

private String userId;

// 用户名称

private String username;

// 用户主机地址

private String host;

// 用户登录时系统IP

private String systemHost;

// 状态

private String status;

// session创建时间

private Date startTimestamp;

// session最后访问时间

private Date lastAccessTime;

// 超时时间

private Long timeout;

// get set略

}

Service

创建一个Service接口,包含查看所有在线用户和根据SessionId踢出用户抽象方法:

public interface SessionService {

List list();

boolean forceLogout(String sessionId);

}

其具体实现:

@Service

public class SessionServiceImpl implements SessionService {

@Autowired

private SessionDAO sessionDAO;

@Override

public List list() {

List list = new ArrayList<>();

Collection sessions = sessionDAO.getActiveSessions();

for (Session session : sessions) {

UserOnline userOnline = new UserOnline();

TbUser user;

SimplePrincipalCollection principalCollection;

if (session.getAttribute(DefaultSubjectContext.PRINCIPALS_SESSION_KEY) == null) {

continue;

} else {

principalCollection = (SimplePrincipalCollection) session

.getAttribute(DefaultSubjectContext.PRINCIPALS_SESSION_KEY);

user = (TbUser) principalCollection.getPrimaryPrincipal();

userOnline.setUsername(user.getUserName());

userOnline.setUserId(user.getId().toString());

}

userOnline.setId((String) session.getId());

userOnline.setHost(session.getHost());

userOnline.setStartTimestamp(session.getStartTimestamp());

userOnline.setLastAccessTime(session.getLastAccessTime());

Long timeout = session.getTimeout();

if (timeout == 0L) {

userOnline.setStatus("离线");

} else {

userOnline.setStatus("在线");

}

userOnline.setTimeout(timeout);

list.add(userOnline);

}

return list;

}

@Override

public boolean forceLogout(String sessionId) {

Session session = sessionDAO.readSession(sessionId);

session.setTimeout(0);

return true;

}

}

通过SessionDao的getActiveSessions()方法,我们可以获取所有有效的Session,通过该Session,我们还可以获取到当前用户的Principal信息。

值得说明的是,当某个用户被踢出后(Session Time置为0),该Session并不会立刻从ActiveSessions中剔除,所以我们可以通过其timeout信息来判断该用户在线与否。

如果使用的Redis作为缓存实现,那么,forceLogout()方法需要稍作修改:

@Override

public boolean forceLogout(String sessionId) {

Session session = sessionDAO.readSession(sessionId);

sessionDAO.delete(session);

return true;

}

Controller

定义一个SessionContoller,用于处理Session的相关操作:

@Controller

@RequestMapping("/online")

public class SessionController {

@Autowired

SessionService sessionService;

@RequestMapping("/index")

public String online() {

return "online";

}

@ResponseBody

@RequestMapping("/list")

public List list() {

return sessionService.list();

}

@ResponseBody

@RequestMapping("/forceLogout")

public AjaxResult forceLogout(String id) {

try {

sessionService.forceLogout(id);

return AjaxResult.success();

} catch (Exception e) {

e.printStackTrace();

return AjaxResult.error("踢出用户失败");

}

}

}

页面

我们编写一个online.html页面,用于展示所有在线用户的信息:

在线用户管理

table {

margin: 20px 40px 20px 0px;

width: 100%;

border-collapse: collapse;

border-spacing: 0;

table-layout: automatic;

word-wrap: break-all

}

table > tbody > tr:nth-of-type(odd) {

background-color: #F7F7F7

}

th, td {

padding: 8px;

text-align: left;

vertical-align: middle;

font-weight: normal;

font-size: 12px;

border-bottom: 1px solid #fff;

}

th {

padding-bottom: 10px;

color: #fff;

font-weight: 700;

background: rgba(66, 185, 131, .9)

}

td {

border-bottom-width: 1px

}

在线用户数:

序号用户名称登录时间最后访问时间主机状态操作

返回

var ctx = [[@{/}]];

$.get(ctx + "online/list", {}, function (r) {

console.log(r);

var length = r.length;

$("#onlineCount").text(length);

var html = "";

for (var i = 0; i < length; i++) {

html += "

"

+ "

" + (i + 1) + ""

+ "

" + r[i].username + ""

+ "

" + r[i].startTimestamp + ""

+ "

" + r[i].lastAccessTime + ""

+ "

" + r[i].host + ""

+ "

" + r[i].status + ""

+ "

下线"

+ "

";

}

$("table").append(html);

}, "json");

function offline(id, status) {

if (status == "离线") {

alert("该用户已是离线状态!!");

return;

}

$.get(ctx + "online/forceLogout", {"id": id}, function (r) {

if (r.code == 0) {

alert('该用户已强制下线!');

location.href = ctx + 'online/index';

} else {

alert(r.msg);

}

}, "json");

}

在index.html中加入该页面的入口:

xmlns:th="http://www.thymeleaf.org"

xmlns:shiro="http://www.pollix.at/thymeleaf/shiro">

首页

div {

border: 1px dashed #ddd;

padding: 10px;

margin: 10px 10px 10px 0px;

}

你好![[${user.userName}]]

你的角色为超级管理员

你的角色为测试账户

获取用户信息

新增用户

删除用户

在线用户管理

注销

测试

在主界面点击“在线用户管理”:

image-56-1024x129.png

下线按钮,成功将其强制踢出:

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/397798.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【原创】吟端午

《吟端午》人间六月艳阳天&#xff0c;粽子飘香不等闲。自古离骚东流水&#xff0c;九州沧海变桑田。创作时间&#xff1a;2016年06月08日创作背景&#xff1a;受人之约&#xff0c;赋诗为题&#xff01;转载于:https://blog.51cto.com/yanhuasanyue/1842346

dom对象常用的属性和方法有哪些?

dom对象常用的属性和方法有哪些&#xff1f; 一、总结 一句话总结&#xff1a; 1、document属性和方法&#xff1a;document的属性有head&#xff0c;body之类&#xff0c;方法有各种获取element的方法 2、element的属性和方法&#xff1a;属性比如style&#xff0c;innerHTML和…

html左中右自适应布局,CSS左中右自适应布局六种方案与原理

css虽简单,但细节多,技巧性高,易学难精。如何实现左右固定300px , 中间宽度自适应&#xff1f;有如下结构左右中公有样式, 设置高,设置左右宽度固定300px,左右为红色&#xff0c;中间为黄色。.item {height: 400px;}.left,.right {width: 300px;background: #f00;}.center {bac…

cronschedulebuilder 到时还没运行完_为什么我的软件编译时没问题,运行时却出错?...

首先有件事要和大家说一下&#xff1a;我的公众号现在可以留言了&#xff01;出于种种不可抗力的原因&#xff08;你们懂的&#xff09;&#xff0c;2018 年 3 月 12 号之后注册的公众号将不带有留言功能&#xff0c;并且前三个月内注册但并未使用的公众号的留言功能也会被一并…

使用Javascript正则表达式来格式化XML内容

2019独角兽企业重金招聘Python工程师标准>>> <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"> <html> <head><meta http-equivcontent-type content"text/html; charsetUTF-8"><title>Xml格式化…

Nginx 笔记与总结(3)配置虚拟主机

Nginx 重启的另外一种方式&#xff0c;相当于 kill -HUP cat /usr/local/nginx/logs/nginx.pid&#xff1a; /usr/local/nginx/sbin/nginx -s reload停止 Nginx 的另外一种方式&#xff1a; /usr/local/nginx/sbin/nginx -s stop重读日志文件的另一种方式&#xff0c;相当于 …

计算机如何查找目标,如何使用命令行查找计算机地理位置? | MOS86

有多种方法可以从IP地址中了解计算机的位置&#xff0c;但如果您决定使用命令行查找信息&#xff0c;那么您如何处理&#xff1f;今天今天的问题Screenshot由Paul Fenwick(Flickr)提供。问题SuperUser阅读器AlikElzin-kilaka想知道如何找到一台电脑首先&#xff0c;AlikElzin-k…

Linux Kernel系列 - 黄牛X内核代码凝视

Hanks.Wang - 专注于操作系统与移动安全研究。Linux-Kernel/SELinux/SEAndroid/TrustZone/Encription/MDM Mail - byhankswanggmail.com 牛X的内核代码凝视 大牛的代码质量高稳定性好&#xff0c;并且逻辑清晰易读性比較强&#xff0c;今天看到Linux Kernel红黑树的代码时&a…

HP服务器ile进系统,HP GEN10服务器UEFI安装Windows Sverver 2012 R2教程

1.操作系统&#xff1a;Windows Server 2012 R2 VL with Update (x64) – DVD (Chinese-Simplified)&#xff0c;MSDN下载地址&#xff1a;ed2k://|file|cn_windows_server_2012_r2_vl_with_update_x64_dvd_6052729.iso|5545527296|BD499EBCABF406AB82293DD8A5803493|/2.镜像写…

py文件的操作

文件操作基本流程。 计算机系统分为&#xff1a;计算机硬件&#xff0c;操作系统&#xff0c;应用程序三部分。 我们用python或其他语言编写的应用程序若想要把数据永久保存下来&#xff0c;必须要保存于硬盘中&#xff0c;这就涉及到应用程序要操作硬件&#xff0c;众所周知&a…

CentOS系统启动流程你懂否

一、Linux内核的组成相关概念&#xff1a;Linux系统的组成部分&#xff1a;内核根文件系统内核&#xff1a;进程管理、内存管理、网络协议栈、文件系统、驱动程序。IPC(Inter-Process Communication进程间通信):就是指多个进程之间相互通信&#xff0c;交换信息的方法。Linux I…

debian 访问 windows 共享_【续】windows环境redis未授权利用方式梳理

01Redis未授权产生原因1.redis绑定在0.0.0.0:6379默认端口&#xff0c;直接暴露在公网&#xff0c;无防火墙进行来源信任防护。2.没有设置密码认证&#xff0c;可以免密远程登录redis服务02漏洞危害1.信息泄露&#xff0c;攻击者可以恶意执行flushall清空数据2.可以通过eval执行…

mysql 列数据显示转成行数据显示_Mysql的列修改成行并显示数据的简单实现

创建测试表&#xff1a;DROP TABLE IF EXISTS test;CREATE TABLE test (year int(11) DEFAULT NULL,month int(11) DEFAULT NULL,amount double DEFAULT NULL) ENGINEInnoDB DEFAULT CHARSETutf8;插入数据&#xff1a;INSERT INTO test VALUES (1991, 1, 1.1);INSERT INTO test…

sql获取某列出现频次最多的值_业务硬核SQL集锦

戳上方蓝字关注我 这两年学会了跑sql&#xff0c;当时有很多同学帮助我精进了这个技能&#xff0c;现在也写成一个小教程&#xff0c;反馈给大家。适用对象&#xff1a;工作中能接触到sql查询平台的业务同学(例如有数据查询权限的产品与运营同学)适用场景&#xff1a;查询hive&…

nginx编译安装与配置使用

第一部分----nginx基本应用源码编译安装nginx1、安装pcre软件包&#xff08;使nginx支持http rewrite模块&#xff09;yum install -y pcre yum install -y pcre-devel2、安装openssl-devel&#xff08;使nginx支持ssl&#xff09;yum install -y openssl-devel3、创建用户ngin…

修复 Xcode 错误 “The identity used to sign the executable is no longer valid”

如图&#xff1a; 解决方法来自&#xff1a;http://stackoverflow.com/questions/7088441/the-identity-used-to-sign-the-executable-is-no-longer-valid/14275197 Restarting Xcode didnt work for me. What fixed it for me was going to Accounts in Xcode (in preferences…

centos设置ip

这里是centos7.vmware安装centos后需要设置ip 1.首先查看虚拟机的网络适配器信息 2.根据信息修改配置文件 vi /etc/sysconfig/network-scripts/ifcfg-ens33 图为修改后的,最初的配置为 BOOTPROTOdhcp ONBOOTno IPADDR,GATEWAY,NETMASK没有进行配置需要根据网络适配器配置手动维…

解决Failed to connect session for conifg 故障

服务器升级openssh之后jenkins构建报错了&#xff0c;报错信息如下&#xff1a; Failed to connet or change directory jenkins.plugins.publish_over.BapPublisherException:Failed to connect session for config.....Message [Algorithm negotiation fail] 升级前ssh版本&a…

78oa mysql_78oa系统版本升级方法

可升级版本预览升级方法&#xff1a;1、备份数据库、附件目录、二次开发程序打开开始菜单——控制面板——管理工具——服务&#xff0c;右键点击停止 78oa mysql service 服务&#xff0c;完整复制【D:\78OA\server\modules\storage\data\78oa】(数据库)文件夹至备份区域。完整…

列表、元组、字典、集合的定义、操作与综合练习

l[A,B,C] t{A,B,C}l.append(B)print(l)scores[66,77,88]d{A:66,B:77,C:88} d[B]99 d[D]111 d.pop(C) print(d)s1{A,B,C} s2{A,C,D} print(s1&s2) print(s1|s2) 转载于:https://www.cnblogs.com/chenjunyu666/p/9147417.html