Browse Source

添加保留用户相同OS和Browser的最新两条token方法

zhaojinyu 2 days ago
parent
commit
5a8766be8f

+ 69 - 1
base-modules/service-system/service-system-biz/src/main/java/com/usky/system/service/util/AsyncFactory.java

@@ -3,16 +3,19 @@ package com.usky.system.service.util;
 
 import com.alibaba.fastjson.JSON;
 import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
+import com.ruoyi.common.core.constant.CacheConstants;
 import com.ruoyi.common.core.constant.Constants;
 import com.ruoyi.common.core.utils.ServletUtils;
 import com.ruoyi.common.core.utils.StringUtils;
 import com.ruoyi.common.core.utils.ip.IpUtils;
 import com.usky.common.core.util.SpringContextUtils;
 import com.usky.common.log.aspect.AddressUtils;
+import com.usky.common.redis.core.RedisService;
 import com.usky.system.domain.MceRequestVO;
 import com.usky.system.domain.SysLogininfor;
 import com.usky.system.domain.SysUser;
 import com.usky.system.mapper.SysUserMapper;
+import com.usky.system.model.LoginUser;
 import com.usky.system.service.ISysLogininforService;
 import com.usky.system.service.ISysUserService;
 import com.usky.system.service.MceReceiveService;
@@ -21,7 +24,7 @@ import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 
 import javax.servlet.http.HttpServletRequest;
-import java.util.Collections;
+import java.util.*;
 
 import static com.usky.common.core.utils.ip.IpUtils.getIpAddr;
 
@@ -84,6 +87,8 @@ public class AsyncFactory
         // 如果登录成功,发送微信公众号消息
             if (Constants.LOGIN_SUCCESS.equals(status)) {
                 sendWeChatMessage(logininfor);
+                // 保留用户最新的一个token,删除其他所有token
+                retainLatestToken(username);
             }
         } else if (Constants.LOGIN_FAIL.equals(status)) {
             logininfor.setStatus(String.valueOf(Constants.LOGIN_FAIL_STATUS)); // 使用String.valueOf进行转换
@@ -123,4 +128,67 @@ public class AsyncFactory
         mceRequestVO.setIpAddress(logininfor.getIpaddr());
         mceReceiveService.addMceReceive(mceRequestVO);
     }
+
+    /**
+     * 保留用户相同OS和Browser的最新两条token,删除其他历史token
+     *
+     * @param username 用户名
+     */
+    private static void retainLatestToken(String username) {
+        RedisService redisService = SpringContextUtils.getBean(RedisService.class);
+
+        try {
+            // 获取所有与该用户相关的token键
+            Collection<String> keys = redisService.keys(CacheConstants.LOGIN_TOKEN_KEY + "*");
+            if (keys == null || keys.isEmpty()) {
+                sys_user_logger.warn("Redis密钥为null或为空");
+                return;
+            }
+
+            // 存储该用户的token及其对应的LoginUser对象
+            Map<String, LoginUser> userTokens = new HashMap<>();
+
+            for (String key : keys) {
+                // 检查键是否存在并且未过期
+                if (redisService.hasKey(key)) {
+                    LoginUser user = redisService.getCacheObject(key);
+                    if (user != null && username.equals(user.getUsername())) {
+                        userTokens.put(key, user);
+                    }
+                }
+            }
+
+            if (userTokens.isEmpty()) {
+                sys_user_logger.warn("未找到用户 {} 的任何token", username);
+                return;
+            }
+
+            // 找到最新的token
+            Map<String, List<LoginUser>> groupedTokens = new HashMap<>();
+            for (Map.Entry<String, LoginUser> entry : userTokens.entrySet()) {
+                String osBrowserKey = entry.getValue().getOs() + "-" + entry.getValue().getBrowser();
+                List<LoginUser> tokenList = groupedTokens.computeIfAbsent(osBrowserKey, k -> new ArrayList<>());
+                tokenList.add(entry.getValue());
+            }
+
+            // OS和Browser组合,保留最新的两条token
+            List<String> tokensToDelete = new ArrayList<>();
+            for (List<LoginUser> tokenList : groupedTokens.values()) {
+                Collections.sort(tokenList, Comparator.comparing(LoginUser::getLoginTime).reversed());
+                for (int i = 2; i < tokenList.size(); i++) {
+                    tokensToDelete.add(redisService.getCacheObject(tokenList.get(i).getToken()));
+                }
+            }
+
+            // 删除其他token
+            for (String tokenKey : tokensToDelete) {
+                boolean deleted = redisService.deleteObject(tokenKey);
+                System.out.println("Deleted Token Key: " + tokenKey + ", Result: " + deleted);
+            }
+
+            sys_user_logger.info("用户 {} 的token已清理,仅保留最新的两条token: {}", username, tokensToDelete.size());
+        } catch (Exception ex) {
+            sys_user_logger.error("清理用户 {} 的token时发生错误", username, ex);
+        }
+    }
 }