Selaa lähdekoodia

优化为相同操作系统只能存在最新一条token

zhaojinyu 2 päivää sitten
vanhempi
commit
171ebb7060

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

@@ -19,9 +19,12 @@ import com.usky.system.service.MceReceiveService;
 import eu.bitwalker.useragentutils.UserAgent;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
+import org.springframework.scheduling.annotation.Async;
+import org.springframework.stereotype.Component;
 
 import javax.servlet.http.HttpServletRequest;
 import java.util.*;
+import java.util.concurrent.TimeUnit;
 
 import static com.usky.common.core.utils.ip.IpUtils.getIpAddr;
 
@@ -30,8 +33,8 @@ import static com.usky.common.core.utils.ip.IpUtils.getIpAddr;
  * @author: XiaoYu
  * @date: 2024/08/20 13:58
  */
-public class AsyncFactory
-{
+@Component
+public class AsyncFactory {
     private static final Logger sys_user_logger = LoggerFactory.getLogger("sys-user");
 
     private static final MceReceiveService mceReceiveService = SpringContextUtils.getBean(MceReceiveService.class);
@@ -81,11 +84,11 @@ public class AsyncFactory
         if (StringUtils.equalsAny(status, Constants.LOGIN_SUCCESS, Constants.LOGOUT, Constants.REGISTER)) {
             logininfor.setStatus(String.valueOf(Constants.LOGIN_SUCCESS_STATUS)); // 使用String.valueOf进行转换
 
-        // 如果登录成功,发送微信公众号消息,删除超出规定历史token
+            // 如果登录成功,发送微信公众号消息
             if (Constants.LOGIN_SUCCESS.equals(status)) {
                 sendWeChatMessage(logininfor);
                 // 保留用户相同OS和Browser的最新两条token,删除其他所有token
-                retainLatestToken(username);
+                SpringContextUtils.getBean(AsyncFactory.class).asyncRetainLatestToken(username);
             }
         } else if (Constants.LOGIN_FAIL.equals(status)) {
             logininfor.setStatus(String.valueOf(Constants.LOGIN_FAIL_STATUS)); // 使用String.valueOf进行转换
@@ -95,10 +98,8 @@ public class AsyncFactory
         SpringContextUtils.getBean(ISysLogininforService.class).insertLogininfor(logininfor);
     }
 
-    public static String getBlock(Object msg)
-    {
-        if (msg == null)
-        {
+    public static String getBlock(Object msg) {
+        if (msg == null) {
             msg = "";
         }
         return "[" + msg.toString() + "]";
@@ -127,7 +128,25 @@ public class AsyncFactory
     }
 
     /**
-     * 保留用户相同OS和Browser的最新两条token,删除其他历史token
+     * 异步清理历史token
+     *
+     * @param username 用户名
+     */
+    @Async
+    public void asyncRetainLatestToken(String username) {
+        try {
+            // 等待2秒
+            TimeUnit.SECONDS.sleep(2);
+            // 调用清理token的方法
+            retainLatestToken(username);
+        } catch (InterruptedException e) {
+            Thread.currentThread().interrupt();
+            sys_user_logger.error("异步清理token时发生错误", e);
+        }
+    }
+
+    /**
+     * 保留用户相同OS的最新一个token,删除其他历史token
      *
      * @param username 用户名
      */
@@ -150,6 +169,7 @@ public class AsyncFactory
                 // 检查键是否存在并且未过期
                 if (redisService.hasKey(key)) {
                     LoginUser user = redisService.getCacheObject(key);
+                    sys_user_logger.info("从Redis获取的LoginUser对象: {}", user);
                     if (user != null && username.equals(user.getUsername())) {
                         userTokens.put(key, user);
                     }
@@ -161,24 +181,24 @@ public class AsyncFactory
                 return;
             }
 
-            // 分组逻辑:根据OS和Browser分组
+            // 分组逻辑:根据OS分组
             Map<String, List<Map.Entry<String, LoginUser>>> groupedTokens = new HashMap<>();
             for (Map.Entry<String, LoginUser> entry : userTokens.entrySet()) {
                 LoginUser loginUser = entry.getValue();
                 String os = StringUtils.isEmpty(loginUser.getOs()) ? "未知" : loginUser.getOs();
-                String browser = StringUtils.isEmpty(loginUser.getBrowser()) ? "未知" : loginUser.getBrowser();
-                String osBrowserKey = os + "-" + browser;
-                groupedTokens.computeIfAbsent(osBrowserKey, k -> new ArrayList<>()).add(entry);
+                groupedTokens.computeIfAbsent(os, k -> new ArrayList<>()).add(entry);
             }
 
-            // 删除逻辑:保留最新的两条token,删除其他token
+            // 删除列表
             List<String> tokensToDelete = new ArrayList<>();
             for (List<Map.Entry<String, LoginUser>> entryList : groupedTokens.values()) {
-                // 按照登录时间排序,保留最新的两条token
+                // 按照登录时间降序排序
                 entryList.sort((e1, e2) ->
                         e2.getValue().getLoginTime().compareTo(e1.getValue().getLoginTime())
                 );
-                for (int i = 3; i < entryList.size(); i++) {
+
+                // 只保留最新的一个token,其余的都添加到tokensToDelete列表中
+                for (int i = 1; i < entryList.size(); i++) {
                     String keyToDelete = entryList.get(i).getKey();
                     tokensToDelete.add(keyToDelete);
                 }
@@ -200,7 +220,7 @@ public class AsyncFactory
                 }
             }
 
-            sys_user_logger.info("用户 {} 的token已清理,仅保留最新的两条token: 已删除{}个", username, tokensToDelete.size());
+            sys_user_logger.info("用户 {} 的token已清理,仅保留每种OS的最新token: 已删除{}个", username, tokensToDelete.size());
         } catch (Exception ex) {
             sys_user_logger.error("清理用户 {} 的token时发生错误", username, ex);
         }