日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 前端技术 > javascript >内容正文

javascript

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

發布時間:2023/12/9 javascript 35 豆豆
生活随笔 收集整理的這篇文章主要介紹了 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}]]

你的角色為超級管理員

你的角色為測試賬戶

獲取用戶信息

新增用戶

刪除用戶

在線用戶管理

注銷

測試

在主界面點擊“在線用戶管理”:

下線按鈕,成功將其強制踢出:

總結

以上是生活随笔為你收集整理的shiro会话监听_SpringBoot集成Shiro会话管理的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。