提交 f5754952 编写于 作者: lakernote's avatar lakernote

(新增)[整体](在线用户管理,设置用户会话有效期30分钟)

上级 3b499e1a
package com.laker.admin.framework.ext.satoken;
import cn.dev33.satoken.SaManager;
import cn.dev33.satoken.dao.SaTokenDao;
import cn.dev33.satoken.listener.SaTokenListener;
import cn.dev33.satoken.stp.SaLoginModel;
import cn.dev33.satoken.stp.StpUtil;
......@@ -12,6 +14,7 @@ import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import javax.annotation.PostConstruct;
import java.util.Date;
import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;
......@@ -27,6 +30,11 @@ public class MySaTokenListener implements SaTokenListener {
@Autowired
ISysUserService sysUserService;
@PostConstruct
public void init() {
initRefreshThread();
}
/**
* 每次登录时触发
*/
......@@ -44,7 +52,7 @@ public class MySaTokenListener implements SaTokenListener {
.tokenValue(StpUtil.getTokenValue())
.nickName(sysUserService.getById((Long) loginId).getNickName())
.browser(requestUserAgent.getBrowser().getName()).build());
log.info("user doLogin,useId:{},token:{}",loginId,StpUtil.getTokenValue());
log.info("user doLogin,useId:{},token:{}", loginId, StpUtil.getTokenValue());
}
/**
......@@ -56,7 +64,7 @@ public class MySaTokenListener implements SaTokenListener {
ONLINE_USERS.removeIf(onlineUser ->
onlineUser.getTokenValue().equals(tokenValue)
);
log.info("user doLogout,useId:{},token:{}",loginId,tokenValue);
log.info("user doLogout,useId:{},token:{}", loginId, tokenValue);
}
/**
......@@ -68,7 +76,7 @@ public class MySaTokenListener implements SaTokenListener {
ONLINE_USERS.removeIf(onlineUser ->
onlineUser.getTokenValue().equals(tokenValue)
);
log.info("user doLogoutByLoginId,useId:{},token:{}",loginId,tokenValue);
log.info("user doLogoutByLoginId,useId:{},token:{}", loginId, tokenValue);
}
/**
......@@ -79,7 +87,7 @@ public class MySaTokenListener implements SaTokenListener {
ONLINE_USERS.removeIf(onlineUser ->
onlineUser.getTokenValue().equals(tokenValue)
);
log.info("user doReplaced,useId:{},token:{}",loginId,tokenValue);
log.info("user doReplaced,useId:{},token:{}", loginId, tokenValue);
}
/**
......@@ -103,7 +111,8 @@ public class MySaTokenListener implements SaTokenListener {
*/
@Override
public void doCreateSession(String id) {
// ...
// ...
log.info("user doCreateSession,id:{}", id);
}
/**
......@@ -111,7 +120,67 @@ public class MySaTokenListener implements SaTokenListener {
*/
@Override
public void doLogoutSession(String id) {
// ...
// ...
log.info("user doLogoutSession,id:{}", id);
}
// --------------------- 定时清理过期数据
/**
* 执行数据清理的线程
*/
public Thread refreshThread;
/**
* 是否继续执行数据清理的线程标记
*/
public boolean refreshFlag;
/**
* 初始化定时任务
*/
public void initRefreshThread() {
// 如果配置了<=0的值,则不启动定时清理
if (SaManager.getConfig().getDataRefreshPeriod() <= 0) {
return;
}
// 启动定时刷新
this.refreshFlag = true;
this.refreshThread = new Thread(() -> {
for (; ; ) {
log.info("定时清理过期会话开始。间隔:{}s,在线人数:{}", SaManager.getConfig().getDataRefreshPeriod() + 5, ONLINE_USERS.size());
try {
try {
// 如果已经被标记为结束
if (refreshFlag == false) {
return;
}
long start = System.currentTimeMillis();
ONLINE_USERS.removeIf(onlineUser -> {
long timeout = StpUtil.stpLogic.getTokenActivityTimeoutByToken(onlineUser.getTokenValue());
if (timeout == SaTokenDao.NOT_VALUE_EXPIRE) {
return true;
}
return false;
});
log.info("定时清理过期会话结束,在线人数:{},耗时:{}ms", ONLINE_USERS.size(), System.currentTimeMillis() - start);
} catch (Exception e) {
e.printStackTrace();
}
// 休眠N秒
int dataRefreshPeriod = SaManager.getConfig().getDataRefreshPeriod();
if (dataRefreshPeriod <= 0) {
dataRefreshPeriod = 1;
}
dataRefreshPeriod = dataRefreshPeriod + 5;
Thread.sleep(dataRefreshPeriod * 1000);
} catch (Exception e) {
e.printStackTrace();
}
}
});
refreshThread.start();
}
}
......@@ -17,6 +17,14 @@ public class OnlineUser {
private String city;
private String browser;
private String tokenValue;
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss",timezone = "GMT+8")
/**
* 登录时间
*/
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
private Date loginTime;
/**
* 最近一次操作时间
*/
@JsonFormat(pattern = "yyyy-MM-dd HH:mm:ss", timezone = "GMT+8")
private Date lastActivityTime;
}
package com.laker.admin.module.sys.controller;
import cn.dev33.satoken.SaManager;
import cn.dev33.satoken.annotation.SaCheckLogin;
import cn.dev33.satoken.annotation.SaCheckPermission;
import cn.dev33.satoken.stp.StpUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.crypto.SecureUtil;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
......@@ -17,6 +19,7 @@ import com.laker.admin.framework.aop.Metrics;
import com.laker.admin.framework.cache.ICache;
import com.laker.admin.framework.ext.mybatis.UserInfoAndPowers;
import com.laker.admin.framework.ext.satoken.MySaTokenListener;
import com.laker.admin.framework.ext.satoken.OnlineUser;
import com.laker.admin.module.sys.entity.SysRole;
import com.laker.admin.module.sys.entity.SysUser;
import com.laker.admin.module.sys.entity.SysUserRole;
......@@ -110,9 +113,19 @@ public class LoginController {
@RequestParam(required = false, defaultValue = "10") int limit) {
List<String> sessionIds = StpUtil.searchTokenValue(null, -1, 1000);
log.info("当前用户:{}", Arrays.toString(sessionIds.toArray()));
MySaTokenListener.ONLINE_USERS.sort((o1, o2) -> DateUtil.compare(o2.getLoginTime(), o1.getLoginTime()));
PageDtoUtil pageDto = PageDtoUtil.getPageDto(MySaTokenListener.ONLINE_USERS, page, limit);
log.warn("stp用户数:{},memory用户数:{}", sessionIds.size(), pageDto.getTotal());
return PageResponse.ok(pageDto.getPageList(), (long) pageDto.getTotal());
List<OnlineUser> pageList = (List<OnlineUser>) pageDto.getPageList();
pageList.forEach(onlineUser -> {
String keyLastActivityTime = StpUtil.stpLogic.splicingKeyLastActivityTime(onlineUser.getTokenValue());
String lastActivityTimeString = SaManager.getSaTokenDao().get(keyLastActivityTime);
if (lastActivityTimeString != null) {
long lastActivityTime = Long.parseLong(lastActivityTimeString);
onlineUser.setLastActivityTime(DateUtil.date(lastActivityTime));
}
});
return PageResponse.ok(pageList, (long) pageDto.getTotal());
}
@GetMapping("/api/v1/kickOffline")
......
......@@ -41,7 +41,7 @@ sa-token:
# token名称 (同时也是cookie名称)
token-name: LakerToken
# token有效期,单位s 默认30天, -1代表永不过期
# timeout: 1800
timeout: 1800
# token临时有效期 [指定时间内无操作就视为token过期] (单位: 秒), 默认-1 代表不限制
activity-timeout: 1800
# 是否允许同一账号并发登录 (为true时允许一起登录, 为false时新登录挤掉旧登录)
......
......@@ -76,6 +76,12 @@
field: 'ip',
align: 'center'
},
{
title: '最近操作时间',
field: 'lastActivityTime',
align: 'center'
},
{
title: '登录时间',
field: 'loginTime',
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册