zoukankan      html  css  js  c++  java
  • 如何限制同一用户同时登录多台设备?

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

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

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

    业务代码

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

    // 生成 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,后续再次登录时,需要验证用户是否拥有该角色?验证用户是否限制了同时登陆?

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

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

    // 从 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);
         } 
    } 

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

    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 校验即可,忽略限制用户同时登录角色的校验。

  • 相关阅读:
    从苦逼到牛逼,详解Linux运维工程师的打怪升级之路
    Linux命令学习
    Linux企业运维人员最常用150个命令汇总
    理解Docker
    理解Docker(8):Docker 存储之卷(Volume)
    理解Docker(7):Docker 存储
    理解Docker(6):若干企业生产环境中的容器网络方案
    理解Docker(5):Docker 网络
    理解Docker(4):Docker 容器使用 cgroups 限制资源使用
    理解Docker(3):Docker 使用 Linux namespace 隔离容器的运行环境
  • 原文地址:https://www.cnblogs.com/blogtech/p/13920646.html
Copyright © 2011-2022 走看看