如何限制同一用户同时登录多台设备?

  最近项目出现新需求,产品经理提出一些用户要限制同一用户同时登录多台设备,一些用户不需要限制,也可以在多台设备上同时登录,想了好久没有太多的思路;后面和同事讨论,才想出了使用 redis 缓存当前用户的登录状态,然后根据已登录用户的状态来限制用户再次登录,为用户分配指定角色,根据角色判断是否限制用户同时登录多台设备,下面我就来将具体的步骤罗列出来;

  大致介绍:项目是采用 Shiro + JWT + Redis 来记录当前用户的登录状态,前端登录时,后端通过校验用户名和密码,通过后生成 JWT 并返回给前端,后续每次请求前端都会携带 token 访问后端,后端校验 token 的有效性,进而操作指定的功能。

  解决方案:用户登录时,Redis 再维护以 username【唯一】作为 key,value = token 的键值对数据,并设置一定的过期时长;创建一个限制用户登录的角色 limit_login ,当获取已登录的用户拥有该角色 limit_login 时,就需要判定用户是否有同时登录其他设备。

业务代码

1)用户登录时,JWT 根据用户名,生成加密 token,并保存在 Redis 缓存中;

1
2
3
4
5
6
7
8
9
// 生成 Token
String token = JwtUtil.sign(sysUser.getUsername(), syspassword);
// 缓存用户登录生成的 token,并设置 key 的过期时间
redisUtil.set(CommonConstant.PREFIX_USER_TOKEN + token, token);
redisUtil.expire(CommonConstant.PREFIX_USER_TOKEN + token, JwtUtil.EXPIRE_TIME / 1000);
 
// 缓存用户登录状态,并设置 key 的过期时间
redisUtil.set(CommonConstant.PREFIX_USER_LOGIN_STATUS + username, token);
redisUtil.expire(CommonConstant.PREFIX_USER_LOGIN_STATUS + username, JwtUtil.EXPIRE_TIME / 1000);

2)限制用户同时登陆需要设置指定角色 limit_login_role,后续再次登录时,需要验证用户是否拥有该角色?验证用户是否限制了同时登陆?

1
2
3
4
5
6
private final String limitLoginRole = "limit_login_role";
// 通过用户名获取用户角色列表
List<String> roleList = sysUserService.getRole(username);
if (roleList.contains(limitLoginRole)) {
    throw new RuntimeException("该用户已登录"); 
}

3)用户登录后正常操作系统,需校验 token 有效性,是否过期,校验成功后,刷新 token 和 loginStatus 过期时间

1
2
3
4
5
6
7
8
9
10
11
// 从 Redis 中获取 token 数据
String cacheToken = String.valueOf(redisUtil.get(CommonConstant.PREFIX_USER_TOKEN + token));
if (StringUtils.isNotEmpty(cacheToken)) {
    // 校验token有效性
    if (JwtUtil.verify(token, userName, passWord)) {    // 缓存用户登录生成的 token,并设置 key 的过期时间
       redisUtil.set(CommonConstant.PREFIX_USER_TOKEN + token, token);
       redisUtil.expire(CommonConstant.PREFIX_USER_TOKEN + token, JwtUtil.EXPIRE_TIME / 1000);
 
       // 缓存用户登录状态,并设置 key 的过期时间
       redisUtil.set(CommonConstant.PREFIX_USER_LOGIN_STATUS + username, token);
       redisUtil.expire(CommonConstant.PREFIX_USER_LOGIN_STATUS + username, JwtUtil.EXPIRE_TIME / 1000);     } <br>} 

4)登录登录时,删除 Redis 中的 token 和 loginStatus

1
2
3
4
5
String token = request.getHeader(DefContants.X_ACCESS_TOKEN);
//清空用户Token缓存
redisUtil.del(CommonConstant.PREFIX_USER_TOKEN + sysUser.getUsername());
//清空用户登录状态缓存
redisUtil.del(CommonConstant.PREFIX_USER_LOGIN_STATUS + sysUser.getUsername());

  以上就是通过 Shiro + JWT + Redis 实现限制用户同时登录的核心代码,不管用户有没有分配限制同时登陆的角色,都会保存一个 loginStatus = token 这样一个键值对,如果用户分配了该角色,就会校验,如果用户没分配该角色,直接走之前的 token 校验即可,忽略限制用户同时登录角色的校验。

 

posted @   菜鸟的奋斗之路  阅读(5884)  评论(0编辑  收藏  举报
编辑推荐:
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
阅读排行:
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 地球OL攻略 —— 某应届生求职总结
· 提示词工程——AI应用必不可少的技术
· Open-Sora 2.0 重磅开源!
· 周边上新:园子的第一款马克杯温暖上架
点击右上角即可分享
微信分享提示