当前位置: 首页 > news >正文

如何限制单一用户并发登录数实现互踢机制?

如何限制单一用户并发登录数实现互踢机制?

根据 2025 年 11 月 5 日芋道框架的实现方案,通过在 SecurityProperties.java 中添加 singleLoginEnable=false 配置属性,配合 Redis 存储 userId 与 Token 映射关系,可实现同一用户只能有一个有效登录会话的互踢机制。

原因分析

HTTP 协议是无状态的,服务器不会记住两次请求之间的关系,因此需要 Session 或 Token 机制来识别用户身份。如果没有限制,同一个账号可以在多个设备、多个浏览器上同时登录,这会带来账号共享、安全风险和审计困难三大问题。根据 2025 年 5 月 2 日的单点登录互斥机制资料,这类机制需要服务端存储登录状态并进行比对:登录成功后生成唯一标识 (Token 或 Session ID),保存在数据库或缓存中 (如 Redis),后续用户访问时对比当前请求携带的 Token 与存储中的是否一致,如果不一致则判定为旧会话已失效。

解决方案

方案一:Session + Redis 映射 (传统 Session 架构)

根据 2026 年 4 月 1 日的技术方案,登录时将 userId → sessionId 的映射存入 Redis。新登录时,根据旧的 sessionId 销毁旧 Session,并更新映射。每次请求拦截,校验当前 Session 对应的 userId 是否与 Redis 中存储的最新 sessionId 一致。代码示例 (Java + Redis 伪代码):

// 登录时存储映射
redis.setex("user_session:" + userId, expireTime, sessionId);
// 请求拦截时校验
String storedSessionId = redis.get("user_session:" + userId);
if (!storedSessionId.equals(currentSessionId)) {// 会话已失效,强制登出
}

方案二:Shiro 自定义 Filter 实现并发控制

根据 2023 年 8 月 4 日的 Shiro 实现方案,通过自定义 KickoutSessionFilter 继承 AccessControlFilter,在 shiroConfig 中配置过滤器规则。关键配置参数:maxSession=1(同一个用户最大会话数,默认 -1 不限制),kickoutAfter=false(踢出之前登录的用户)。XML 配置示例:

<bean id="kickoutSessionFilter" class="com.sojson.core.shiro.filter.KickoutSessionFilter"><property name="kickoutUrl" value="/u/login.shtml?kickout"/>
</bean>

方案三:JWT + Redis + Token 版本号 (无状态方案)

根据 2019 年 12 月 11 日的 SpringBoot 并发登录控制方案,JWT(token) 存储在 Redis 中,类似 JSessionId-Session 的关系,用户登录后每次请求在 Header 中携带 jwt。若依项目 2023 年 8 月 3 日的实现中,在 application.yml 新增 soloLogin 配置:

token:# 是否允许账户多终端同时登录 (true 允许 false 不允许)soloLogin: false

TokenService.java 中存储&刷新缓存用户编号信息,使用 Constants.LOGIN_USERID_KEY="login_userid:"作为 Redis key 前缀。

方案四:WebSocket 双工通信实时互踢

根据 2024 年 6 月 13 日的 WebSocket 方案,用户登录成功后生成 uuid 代表 sessionid,客户端建立 WebSocket 连接,使用 hashmap 存储 sessionid 与 WebSocket 的映射关系,同时使用 Redis 存储 userId 与 sessionid 列表的映射关系。当用户在新设备登录时,根据 userId 查询 Redis 中已存在的 sessionid,找到对应的 WebSocket 会话实例并发送消息通知客户端会话已失效。

注意事项

根据多个来源的实际反馈,实现互踢机制时需注意以下问题:

1. 分布式环境必须使用集中存储:2025 年 5 月 2 日资料指出,这类机制一般需要服务端存储登录状态并进行比对,单个节点可用静态 Map 或 Ehcache,但分布式环境必须使用 Redis 等集中缓存。

2. 避免并发竞态:2026 年 4 月 1 日资料提到,登录和校验过程中可能存在并发竞态问题,需要使用原子操作或分布式锁。

3. 主动清理过期数据:若依项目 2023 年 8 月 3 日的实现中,在 delLoginUser 方法中需要同时删除 token 和 userId 对应的缓存记录,避免数据残留。

4. 移动端与多端区分:2026 年 4 月 1 日资料建议,可根据业务需求区分移动端和 Web 端,允许同一账号在不同类型设备上同时登录。

5. 踢出与拒绝的选择:根据 2023 年 8 月 4 日 Shiro 配置,kickoutAfter=false 表示踢出之前登录的用户,如果设置为 true 则拒绝新登录请求,需根据业务场景选择。

参考来源

来源:芋道框架 - 芋道框架实现单点登录:踢出旧登录,让每个账号只能在一处登录 (2025 年 11 月 5 日)

来源:51CTO 博客 - Shiro 控制并发登录人数限制实现,登录踢出实现 (2023 年 8 月 4 日)

来源:若依项目文档 - 若依项目如何实现一个账户只能一个人登录 (2023 年 8 月 3 日)

来源:掘金 - WebSocket 双工通信实现用户互踢功能 (2024 年 6 月 13 日)

原文链接:https://www.zjcp.cc/ask/9686.html

http://www.jsqmd.com/news/755017/

相关文章:

  • 为什么92%的Java团队在外部函数配置上多花3倍调试时间?揭秘ClassLoader隔离、动态库加载顺序与符号冲突隐性规则
  • 别再傻傻分不清了!LM358和LM324到底怎么选?从引脚图到实战应用,一次讲透
  • 从零构建高可用Agent:后端架构实战与避坑指南
  • 大模型为什么会有“幻觉”——从训练方式到推理局限
  • ARM浮点指令集架构与寄存器规范详解
  • ACMER X1三合一加工设备:激光雕刻与CNC铣削全解析
  • 视觉AI虚拟训练平台SPHINX:从原理到工业应用
  • 私有化部署ChatGPT API服务器:从原理到实战部署指南
  • 手把手教你用GLIP实现零样本目标检测:从COCO数据集加载到模型推理全流程
  • 现在不掌握低代码内核调试=主动放弃技术话语权:2024Q3主流平台(Jeecg、LowCodeEngine、AppSmith)内核调试兼容性速查表
  • SANA-Video:基于块线性扩散Transformer的高效视频生成技术
  • 自进化AI系统的社会性风险与安全防护策略
  • ai辅助钱包开发:让快马kimi生成uniswap v3流动性管理组件代码
  • 从‘抓瞎’到‘精准定位’:用Android Profiler内存分析器揪出Fragment和Activity泄漏的完整实战
  • 保姆级教程:在蓝桥杯开发板上用CX20106A超声波测距,从原理图接线到代码调试全流程
  • SQL实战:用论坛发帖表t1,5分钟搞懂UPDATE、WHERE和GROUP BY的核心用法
  • 多模态视频检索技术:从数据集构建到模型部署全解析
  • ARM嵌入式单元测试实战与Tessy框架解析
  • 用GPT-4给Syzkaller打工:手把手教你用KernelGPT自动生成Linux内核模糊测试规约
  • 2025届必备的六大降AI率网站推荐
  • GPT-Codex项目实战:基于LLM的AI编程助手部署与应用指南
  • Discord社区管理革命:用基础设施即代码实现自动化与版本控制
  • 别再手动改注册表了!用Python的winreg模块5分钟搞定自动化配置(附实战代码)
  • 基于meta-cogbase框架构建认知智能体:从核心原理到工程实践
  • 别再空谈Web3了!从协鑫光伏到巡鹰换电,看RWA如何解决新能源行业的真问题
  • 【工业级量子模拟框架设计规范】:ISO/IEC 20987兼容的C++量子比特抽象层实现全披露
  • 基于Web Audio与WebAssembly的浏览器合成器Clawbands开发全解析
  • 3分钟掌握KMS_VL_ALL_AIO:Windows与Office智能激活的终极解决方案
  • SIT-LMPC:机器人控制中的安全迭代优化技术
  • 不只是点灯:深入解读Infineon TC3xx MCAL Demo如何帮你验证片内外设驱动