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.pswp.cn/news/397798.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/397798.shtml
英文地址,請注明出處:http://en.pswp.cn/news/397798.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

JAVA程序員面試必知32個知識點

第一&#xff0c;談談final, finally, finalize的區別。 final 用于聲明屬性&#xff0c;方法和類&#xff0c;分別表示屬性不可變&#xff0c;方法不可覆蓋&#xff0c;類不可繼承。finally是異常處理語句結構的一部分&#xff0c;表示總是執行。finalize是 Object類的一個方法…

html 將兩個標簽綁在一起,基本標簽2

表格的合并1.水平方向上的單元格合并可以給td標簽添加一個colspan屬性, 來指定把某一個單元格當做多個單元格來看待(水平方向)例如:含義: 把當前單元格當做兩個單元格來看待注意點:1.由于把某一個單元格當做了多個單元格來看到, 所以就會多出一些單元格, 所以需要刪掉一些單元格…

【原創】吟端午

《吟端午》人間六月艷陽天&#xff0c;粽子飄香不等閑。自古離騷東流水&#xff0c;九州滄海變桑田。創作時間&#xff1a;2016年06月08日創作背景&#xff1a;受人之約&#xff0c;賦詩為題&#xff01;轉載于:https://blog.51cto.com/yanhuasanyue/1842346

libc 無法訪問null_C中strlen的NULL參數

1. C語言strlen函數參數如果是NULL&#xff0c;則會出錯。可以參考glibc中strlen的具體實現通常使用前可以判斷一下參數是否是NULL&#xff0c;或者自己寫一個strlen的實現函數。2. String LengthYou can get the length of a string using the strlen function.This function …

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…

cacti 忘記密碼的方法

忘記密碼的方法如果是admin 的密碼丟失&#xff0c;id 1&#xff1b;其他用戶以此類推。進入mysqlmysql> show databases; mysql> use cacti;mysql> show tables; mysql> update user_auth set passwordmd5("newpassword") where id1;新的cacti密碼就是…

cr3格式是什么意思_佳能rp的cr3如何打開?修圖為什么要用raw格式?轉碼又是什么?...

佳能rp的cr3如何打開&#xff1f;修圖為什么要用raw格式&#xff1f;轉碼又是什么&#xff1f;這是我個人整理的廣大網友的一些答案&#xff0c;不想浪費大家太多時間就在這里分享給大家希望大家可以快速理解。(搜集的廣大網友的回答&#xff0c;方便大家理解&#xff0c;希望他…

SGU traffic light

占位置。。轉載于:https://www.cnblogs.com/usedrosee/p/4669358.html

計算機基礎應用的培養活動記錄,計算機應用基礎綜合實訓

摘要&#xff1a;《計算機應用基礎綜合實訓(Windows7Office 2010 第3版)》是中等職業教育課程改革國家規劃新教材,根據教育部2009年頒布的"中等職業學校計算機應用基礎教學大綱"中職業模塊的要求編寫,在第2版的基礎上修訂而成,經全國中等職業教育教材審定委員會審定通…

cronschedulebuilder 到時還沒運行完_為什么我的軟件編譯時沒問題,運行時卻出錯?...

首先有件事要和大家說一下&#xff1a;我的公眾號現在可以留言了&#xff01;出于種種不可抗力的原因&#xff08;你們懂的&#xff09;&#xff0c;2018 年 3 月 12 號之后注冊的公眾號將不帶有留言功能&#xff0c;并且前三個月內注冊但并未使用的公眾號的留言功能也會被一并…

Canvas createImageData

createImageData() 方法創建新的空白 ImageData 對象。新對象的默認像素值 transparent black。 對于 ImageData 對象中的每個像素&#xff0c;都存在著四方面的信息&#xff0c;即 RGBA 值&#xff1a; R - 紅色 (0-255)G - 綠色 (0-255)B - 藍色 (0-255)A - alpha 通道 (0-25…

青島計算機類職業中學,青島最好的職業學校有哪些?

青島海洋職業學校是一所由青島市教育局批準&#xff0c;國家承認學歷的重點中等職業學校。學校占地200余畝&#xff0c;建筑面積5萬平方米&#xff0c;在籍學生3975人。學校擁有雄厚的師資力量&#xff0c;以專職教師為主&#xff0c;是一支政治素質好&#xff0c;師德水平高、…

測試1

2018/06/03 測試我的隨筆轉載于:https://www.cnblogs.com/xixirui/p/9129252.html

使用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格式化…

mysql vfp_vfp+mysql問題|交流區 - 梅子Visual FoxPro 編程 - Powered by phpwind

感謝樓上,請現場指導,拜謝c_pzwhfiellist""c_pzwhbglist""For i1 To Fcount()-1c_pzwhfiellistc_pzwhfiellistField(i)","c_pzwhbglistc_pzwhbglistField(i)Space(1)"pzwhk."Field(i)","Chr(10)Endforc_pzwhfiellistc_pzwhf…

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…

Nmap命令的常用實例

一、Nmap簡介 nmap是一個網絡連接端掃描軟件&#xff0c;用來掃描網上電腦開放的網絡連接端。確定哪些服務運行在哪些連接端&#xff0c;并且推斷計算機運行哪個操作系統&#xff08;這是亦稱 fingerprinting&#xff09;。它是網絡管理員必用的軟件之一&#xff0c;以及用以評…

mysql sqlexception_c-很奇怪-mysql的sql :: SQLException未被其類型捕...

我正在使用帶有此(稍微簡化)代碼的mysql c連接器.try{statement->setString(1, word);statement->executeUpdate();}catch( sql::SQLException& e ){// I dont get herereturn sqlerrno_to_error_code( e.getErrorCode() );}catch( std::exception& e ){// I do …