You need to enable JavaScript to run this app. 基于JWT令牌的在线用户列表获取及在线状态标识方案咨询
优惠活动
大模型
产品
解决方案
定价
更多

基于JWT令牌的在线用户列表获取及在线状态标识方案咨询

在线用户列表服务实现方案

现有代码问题

你当前使用的HttpSession和SessionRegistry是基于服务端会话的状态管理方案,和JWT无状态的特性不兼容:JWT默认不会存储到服务端Session中,因此现有代码无法正确获取JWT登录的用户在线状态。

是否需要将登录信息存储到MongoDB

需要,因为JWT本身无状态,要维护在线用户列表必须主动在服务端存储会话状态,MongoDB完全可以用来承载这部分数据,建议存储的字段如下:

  • 用户邮箱/用户ID
  • JWT的唯一标识jti(不要存储完整JWT明文,避免泄露风险)
  • 令牌过期时间
  • 最后活跃时间
  • 有效状态标记

存储逻辑:

  • 用户登录成功生成JWT时,插入一条有效状态为true的记录
  • 用户主动登出时,将对应jti的记录标记为无效,或直接删除

未主动登出的用户处理方案

可以通过两种机制结合处理:

  • 依赖JWT自带的过期时间:查询在线用户时直接过滤掉过期时间小于当前时间的记录,即使未主动登出,令牌过期后自动判定为离线
  • 新增心跳机制(适合需要更精准在线状态的场景):前端每隔30s-1min向后端发送心跳请求,后端更新对应用户的最后活跃时间,查询在线用户时只保留最后活跃时间在5分钟以内的记录,用户关闭页面后无心跳更新,到期自动判定为离线

如果追求更高的读写性能,也可以用Redis代替MongoDB存储会话状态,Redis支持自动设置键过期时间,到期自动删除无效会话,不需要手动过滤过期记录。

接口改造示例

你可以把原有getActiveUsers方法调整为从MongoDB/Redis中查询有效会话:

@CrossOrigin
@GetMapping("/api/getActiveUsers")
public ResponseEntity<Object> activeUser() {
    try {
        // 从MongoDB查询符合条件的在线用户:有效、未过期、最后活跃时间在阈值内
        List<String> onlineUserEmails = userSessionRepository.findOnlineUsers(LocalDateTime.now())
                .stream()
                .map(UserSession::getEmail)
                .collect(Collectors.toList());
        // 如果需要返回所有用户并标注在线状态,查询全量用户列表和在线列表匹配即可
        return ResponseEntity.ok().body(onlineUserEmails); 
    } catch (Exception e) {
        e.printStackTrace();
        throw e;
    }
}

内容的提问来源于stack exchange,提问作者The Old County

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.08 13:09:02