码农知识堂 - 1000bd
  •   Python
  •   PHP
  •   JS/TS
  •   JAVA
  •   C/C++
  •   C#
  •   GO
  •   Kotlin
  •   Swift
  • RuoYi-Cloud版本限制一个账户只能在一个地方登陆


    RuoYi-Cloud版本限制一个账户只能在一个地方登陆

    • 一. 前言
    • 二. 参考
    • 三. 代码实现
      • 三.一 在ruoyi-auth模块下的bootstrap.yml文件下新增一个配置soloLogin用于限制多终端同时登录。
      • 三.二 我是在CacheConstants.java下添加用户缓存的常量
      • 三.三 修改 TokenService.java类下的方法
      • 三.四 修改登录方法SysLoginService.java,验证如果用户不允许多终端同时登录,清除缓存信息
      • 三.五 修改AuthLogic.java中会话注销方法
    • 四. 总结

    一. 前言

    目前框架用的是RuoYi-Cloud版本:https://github.com/yangzongzhuan/RuoYi-Cloud
    业务需求:同一个账户只能在一个地方登陆,后登录的账号挤掉之前登陆的账号

    二. 参考

    参考了若依分离版,后面有改动 如何限制账户不允许多终端登录 https://doc.ruoyi.vip/ruoyi-vue/other/faq.html#%E5%A6%82%E4%BD%95%E9%99%90%E5%88%B6%E8%B4%A6%E6%88%B7%E4%B8%8D%E5%85%81%E8%AE%B8%E5%A4%9A%E7%BB%88%E7%AB%AF%E7%99%BB%E5%BD%95

    三. 代码实现

    三.一 在ruoyi-auth模块下的bootstrap.yml文件下新增一个配置soloLogin用于限制多终端同时登录。

    # token配置
    token:
      # 是否允许账户多终端同时登录(true允许 false不允许)
      soloLogin: false
    
    • 1
    • 2
    • 3
    • 4

    如图:在这里插入图片描述
    在ruoyi-system模块下的bootstrap.yml也同样加上

    三.二 我是在CacheConstants.java下添加用户缓存的常量

     /**
         * 登录用户编号 redis key
         */
        public static final String LOGIN_USERID_KEY = "login_userid:";
    
    • 1
    • 2
    • 3
    • 4

    三.三 修改 TokenService.java类下的方法

        /**
         * 是否允许账户多终端同时登录(true允许 false不允许)
         */
        @Value("${token.soloLogin}")
        private boolean soloLogin;
    
    • 1
    • 2
    • 3
    • 4
    • 5

    修改方法:

    
      /**
         * 删除用户缓存信息
         */
        public void delLoginUser(String token, Long userId) {
            if (StringUtils.isNotEmpty(token)) {
                String userkey = JwtUtils.getUserKey(token);
                redisService.deleteObject(getTokenKey(userkey));
            }
            if (!soloLogin && StringUtils.isNotNull(userId)) {
                String userIdKey = getUserIdKey(userId);
                redisService.deleteObject(userIdKey);
            }
        }
        /**
        
         * 刷新令牌有效期
         *
         * @param loginUser 登录信息
         */
      public void refreshToken(LoginUser loginUser) {
            loginUser.setLoginTime(System.currentTimeMillis());
            loginUser.setExpireTime(loginUser.getLoginTime() + expireTime * MILLIS_MINUTE);
            // 根据uuid将loginUser缓存
            String userKey = getTokenKey(loginUser.getToken());
            redisService.setCacheObject(userKey, loginUser, expireTime, TimeUnit.MINUTES);
            if (!soloLogin)
            {
                // 缓存用户唯一标识,防止同一帐号,同时登录
                String userIdKey = getUserIdKey(loginUser.getSysUser().getUserId());
                redisService.setCacheObject(userIdKey, userKey, expireTime, TimeUnit.MINUTES);
            }
        }
    
        private String getTokenKey(String token) {
            return ACCESS_TOKEN + token;
        }
    
        private String getUserIdKey(Long userId)
        {
            return CacheConstants.LOGIN_USERID_KEY + userId;
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42

    三.四 修改登录方法SysLoginService.java,验证如果用户不允许多终端同时登录,清除缓存信息

     /**
         * 是否允许账户多终端同时登录(true允许 false不允许)
         */
        @Value("${token.soloLogin}")
        private boolean soloLogin;
    
        /**
         * 登录
         */
        public LoginUser login(String username, String password)
        {
          ==================前面的代码============
            LoginUser userInfo = userResult.getData();
            SysUser user = userResult.getData().getSysUser();
          ==================我在这里加判断的 新增的代码============
            if (!soloLogin)
            {
                // 如果用户不允许多终端同时登录,清除缓存信息
                String userIdKey = CacheConstants.LOGIN_USERID_KEY + user.getUserId();
                String userKey = redisService.getCacheObject(userIdKey);
                if (StringUtils.isNotEmpty(userKey))
                {
                    redisService.deleteObject(userIdKey);
                    redisService.deleteObject(userKey);
                }
            }
           ===============后面的代码===========
            return userInfo;
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29

    三.五 修改AuthLogic.java中会话注销方法

      /**
         * 会话注销,根据指定Token
         */
        public void logoutByToken(String token)
        {
            LoginUser loginUser = getLoginUser(token);
            if(loginUser!=null){
                tokenService.delLoginUser(token,loginUser.getUserid());
            }else{
                tokenService.delLoginUser(token,null);
            }
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    这里是用户注销的时候调用的。

    四. 总结

    思路就是:修改redis登录的key,目前的key只存放了token,修改为userid(id为唯一) + key的方式去判断,登录前判断redis中当前登录用户是否已经登录,如果已经登录删除已经存在的token和userId。

  • 相关阅读:
    Linux进阶-ipc共享内存
    【前端设计模式】之责任链模式
    threadx netxduo stm32f407上实现http server
    CSS常用属性(二)
    搭建Spark开发环境
    2023年眼镜行业分析(京东眼镜销量数据分析):市场规模同比增长26%,消费需求持续释放
    面向对象编程之断言assert
    物联网实训室解决方案2024
    kettle遇到的问题-脚本启动系统找不到指定路径
    【Flink实战】玩转Flink里面核心的Sink Operator实战
  • 原文地址:https://blog.csdn.net/erpenggg/article/details/128076092
  • 最新文章
  • 攻防演习之三天拿下官网站群
    数据安全治理学习——前期安全规划和安全管理体系建设
    企业安全 | 企业内一次钓鱼演练准备过程
    内网渗透测试 | Kerberos协议及其部分攻击手法
    0day的产生 | 不懂代码的"代码审计"
    安装scrcpy-client模块av模块异常,环境问题解决方案
    leetcode hot100【LeetCode 279. 完全平方数】java实现
    OpenWrt下安装Mosquitto
    AnatoMask论文汇总
    【AI日记】24.11.01 LangChain、openai api和github copilot
  • 热门文章
  • 十款代码表白小特效 一个比一个浪漫 赶紧收藏起来吧!!!
    奉劝各位学弟学妹们,该打造你的技术影响力了!
    五年了,我在 CSDN 的两个一百万。
    Java俄罗斯方块,老程序员花了一个周末,连接中学年代!
    面试官都震惊,你这网络基础可以啊!
    你真的会用百度吗?我不信 — 那些不为人知的搜索引擎语法
    心情不好的时候,用 Python 画棵樱花树送给自己吧
    通宵一晚做出来的一款类似CS的第一人称射击游戏Demo!原来做游戏也不是很难,连憨憨学妹都学会了!
    13 万字 C 语言从入门到精通保姆级教程2021 年版
    10行代码集2000张美女图,Python爬虫120例,再上征途
Copyright © 2022 侵权请联系2656653265@qq.com    京ICP备2022015340号-1
正则表达式工具 cron表达式工具 密码生成工具

京公网安备 11010502049817号