Files
easygoadmin-wiki/EasyGoAdmin_GoFrame_AntdVue/zh/modules/online-user.md
T
2026-10-20 21:53:26 +08:00

83 lines
3.6 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 6.16 在线用户监控
:::tip 概述
在线用户是无表模块(数据源 Redis):登录/刷新登记会话,分页查看在线列表,强退踢出(access+refresh 双令牌拉黑,防被踢会话经刷新复活)。路由前缀 /api/onlineUser。
:::
## 数据结构(Redis)
```text
zset easygoadmin:online:jti:set score = 访问令牌过期时间戳
键 easygoadmin:online:info:{jti} JSON 详情(TTL = access 剩余期 + 60s)
onlineInfo 字段:
jti / userId / username / realname / ip / location / os / browser /
loginTime / issuedAt / expireAt / refreshJti / refreshIssuedAt / refreshExpireAt /
accessToken / refreshToken(令牌原文,仅详情查看返回)/ tokenType / expiresIn
```
## 会话生命周期
```text
登录/refresh 成功
│ MarkOnline
▼
┌─────────────────────────────────────────────┐
│ zset easygoadmin:online:jti:set │ score=access过期ts
│ 键 easygoadmin:online:info:{jti} = JSON │ TTL=access剩余+60s
└──────────────────┬──────────────────────────┘
页面访问(有效期内)│ │登出 Logout / 强退 ForceLogout
(token 有效,│ ▼ MarkOffline + access/refresh 双拉黑
JWT 放行) │ zset 移除 + info 删除 → 会话消失
▼
access 到期:zset score < now 被区间过滤(列表不可见);
info 键 TTL 到期自动清除
refresh 到期:无法再换新令牌
无心跳/续期机制:会话有效期即 access 令牌有效期(2h);
前端 refresh 轮换会刷新在线登记(MarkOnline 覆盖写)
```
## 接口清单
| 方法 | 路由 | 权限 | 说明 |
|------|------|------|------|
| GET | /api/onlineUser/page | sys:onlineUser:page | 在线会话分页 |
| GET | /api/onlineUser/detail/:id | sys:onlineUser:detail | 会话详情(含令牌原文) |
| GET | /api/onlineUser/forceLogout/:id | sys:onlineUser:forceLogout | 单会话强退 |
| GET | /api/onlineUser/forceLogoutUser/:userId | sys:onlineUser:forceLogout | 踢出该用户全部设备 |
## Page 流程
```text
ZRangeByScore(now..+∞) → 逐 jti 读详情 → username/ip 子串过滤
→ 按登录时间倒序 → 同用户多会话标注(SessionNo/Sessions 序号与总数)
→ 批量回填头像(按 userId 查 user.avatar,GetFileUrl 补域名,单用户只查一次)
→ 内存分页(NewPageData)
```
## 强退的双令牌拉黑(安全关键)
```text
单会话强退(forceLogout/:id):
1) access jti 拉黑(TTL=剩余期+60s)
2) refresh jti 一并拉黑——防被踢会话经 refresh 换新令牌复活
3) MarkOffline(zset 移除 + info 删除)
踢全部设备(forceLogoutUser/:userId):
遍历 zset 匹配 userId → 逐会话双令牌拉黑 + 注销
```
::: tip 为什么双拉黑
只拉黑 access 的话,被踢用户的 refresh_token 仍能兑换新令牌对重新"复活"。access+refresh 一并拉黑才能真正踢出。
:::
## 排障
| 症状 | 原因 |
|------|------|
| 在线列表为空但有人在线 | Redis 内存降级(各实例独立);或会话已过 access 有效期 |
| 强退后对方仍能请求 | 该实例内存降级(黑名单不跨实例);等窗口或查 /api/cache/info |
| 会话数偏多 | access 2h 有效期内多次登录=多会话(同用户多设备标注序号) |
| 详情泄露令牌原文 | 设计如此(运维排查用),依赖 sys:onlineUser:detail 权限收口 |