From b9c9e52187fd8f47218ddefa514987c59d98f72c Mon Sep 17 00:00:00 2001
From: hjl <1657978663@qq.com>
Date: 星期四, 20 六月 2024 11:25:07 +0800
Subject: [PATCH] fix: 学习端bug

---
 ruoyi-common/ruoyi-common-security/src/main/java/com/ruoyi/common/security/service/TokenService.java |  192 +++++++++++++++++++++++++++--------------------
 1 files changed, 110 insertions(+), 82 deletions(-)

diff --git a/ruoyi-common/ruoyi-common-security/src/main/java/com/ruoyi/common/security/service/TokenService.java b/ruoyi-common/ruoyi-common-security/src/main/java/com/ruoyi/common/security/service/TokenService.java
index d114fd9..963d895 100644
--- a/ruoyi-common/ruoyi-common-security/src/main/java/com/ruoyi/common/security/service/TokenService.java
+++ b/ruoyi-common/ruoyi-common-security/src/main/java/com/ruoyi/common/security/service/TokenService.java
@@ -1,7 +1,9 @@
 package com.ruoyi.common.security.service;
 
+import com.alibaba.fastjson2.JSONObject;
 import com.ruoyi.common.core.constant.CacheConstants;
 import com.ruoyi.common.core.constant.SecurityConstants;
+import com.ruoyi.common.core.exception.user.StudyLoginException;
 import com.ruoyi.common.core.utils.JwtUtils;
 import com.ruoyi.common.core.utils.ServletUtils;
 import com.ruoyi.common.core.utils.StringUtils;
@@ -17,6 +19,7 @@
 import javax.servlet.http.HttpServletRequest;
 import java.util.HashMap;
 import java.util.Map;
+import java.util.Set;
 import java.util.concurrent.TimeUnit;
 
 /**
@@ -25,8 +28,7 @@
  * @author ruoyi
  */
 @Component
-public class TokenService
-{
+public class TokenService {
     @Autowired
     private RedisService redisService;
 
@@ -38,13 +40,14 @@
 
     private final static String ACCESS_TOKEN = CacheConstants.LOGIN_TOKEN_KEY;
 
+    private final static String ACCESS_TOKEN_STUDY = CacheConstants.LOGIN_TOKEN_KEY_STUDY;
+
     private final static Long MILLIS_MINUTE_TEN = CacheConstants.REFRESH_TIME * MILLIS_MINUTE;
 
     /**
      * 创建令牌
      */
-    public Map<String, Object> createToken(LoginUser loginUser)
-    {
+    public Map<String, Object> createToken(LoginUser loginUser) {
         String token = IdUtils.fastUUID();
         Long userId = loginUser.getSysUser().getUserId();
         String userName = loginUser.getSysUser().getUserName();
@@ -66,8 +69,8 @@
         rspMap.put("expires_in", expireTime);
         return rspMap;
     }
-    public Map<String, Object> createToken1(LoginUserParent loginUser)
-    {
+
+    public Map<String, Object> createToken1(LoginUserParent loginUser) {
         String token = IdUtils.fastUUID();
         Integer userId = loginUser.getUserid();
         String name = loginUser.getName();
@@ -86,8 +89,7 @@
         return rspMap;
     }
 
-    public Map<String, Object> createTokenStudy(LoginUserParent loginUser)
-    {
+    public Map<String, Object> createTokenStudy(LoginUserParent loginUser) {
         String token = IdUtils.fastUUID();
         Integer userId = loginUser.getUserid();
         String name = loginUser.getName();
@@ -111,8 +113,7 @@
      *
      * @return 用户信息
      */
-    public LoginUser getLoginUser()
-    {
+    public LoginUser getLoginUser() {
         return getLoginUser(ServletUtils.getRequest());
     }
 
@@ -121,19 +122,18 @@
      *
      * @return 用户信息
      */
-    public LoginUser getLoginUser(HttpServletRequest request)
-    {
+    public LoginUser getLoginUser(HttpServletRequest request) {
         // 获取请求携带的令牌
         String token = SecurityUtils.getToken(request);
         return getLoginUser(token);
     }
+
     /**
      * 家长端/学习端获取用户身份信息
      *
      * @return 用户信息
      */
-    public LoginUserParent getLoginUser1()
-    {
+    public LoginUserParent getLoginUser1() {
         return getLoginUser1(ServletUtils.getRequest());
     }
 
@@ -142,9 +142,12 @@
      *
      * @return 用户信息
      */
-    public LoginUserParent getLoginUserStudy()
-    {
-        return getLoginUserStudy(ServletUtils.getRequest());
+    public LoginUserParent getLoginUserStudy() {
+        LoginUserParent userStudy = getLoginUserStudy(ServletUtils.getRequest());
+        if (null == userStudy) {
+            throw new StudyLoginException("登录失效,请重新登录!", 600);
+        }
+        return userStudy;
     }
 
     /**
@@ -152,8 +155,7 @@
      *
      * @return 用户信息
      */
-    public LoginUserParent getLoginUser1(HttpServletRequest request)
-    {
+    public LoginUserParent getLoginUser1(HttpServletRequest request) {
         // 获取请求携带的令牌
         String token = SecurityUtils.getToken(request);
         return getLoginUser1(token);
@@ -164,8 +166,7 @@
      *
      * @return 用户信息
      */
-    public LoginUserParent getLoginUserStudy(HttpServletRequest request)
-    {
+    public LoginUserParent getLoginUserStudy(HttpServletRequest request) {
         // 获取请求携带的令牌
         String token = SecurityUtils.getToken(request);
         return getLoginUserStudy(token);
@@ -176,42 +177,33 @@
      *
      * @return 用户信息
      */
-    public LoginUser getLoginUser(String token)
-    {
+    public LoginUser getLoginUser(String token) {
         LoginUser user = null;
-        try
-        {
-            if (StringUtils.isNotEmpty(token))
-            {
+        try {
+            if (StringUtils.isNotEmpty(token)) {
                 String userkey = JwtUtils.getUserKey(token);
                 user = redisService.getCacheObject(getTokenKey(userkey));
                 return user;
             }
-        }
-        catch (Exception e)
-        {
+        } catch (Exception e) {
         }
         return user;
     }
+
     /**
      * 家长端 学习端 获取用户身份信息
      *
      * @return 用户信息
      */
-    public LoginUserParent getLoginUser1(String token)
-    {
+    public LoginUserParent getLoginUser1(String token) {
         LoginUserParent user = null;
-        try
-        {
-            if (StringUtils.isNotEmpty(token))
-            {
+        try {
+            if (StringUtils.isNotEmpty(token)) {
                 String userkey = JwtUtils.getUserKey1(token);
                 user = redisService.getCacheObject(getTokenKey(userkey));
                 return user;
             }
-        }
-        catch (Exception e)
-        {
+        } catch (Exception e) {
             e.printStackTrace();
         }
         return user;
@@ -222,21 +214,24 @@
      *
      * @return 用户信息
      */
-    public LoginUserParent getLoginUserStudy(String token)
-    {
+    public LoginUserParent getLoginUserStudy(String token) {
         LoginUserParent user = null;
-        try
-        {
-            if (StringUtils.isNotEmpty(token))
-            {
-                String userkey = JwtUtils.getUserKeyStudy(token);
-                user = redisService.getCacheObject(getTokenKey(userkey));
-                return user;
-            }
-        }
-        catch (Exception e)
-        {
-            e.printStackTrace();
+        if (StringUtils.isNotEmpty(token)) {
+            String userkey = JwtUtils.getUserKeyStudy(token);
+            user = redisService.getCacheObject(getTokenKeyStudy(userkey));
+            // 再次判断登录状态是否已过期
+//            if (null == user) {
+//                throw new StudyLoginException("登录信息已过期,请重新登录!", 504);
+//            }
+//            // 优先判断当前账号是否已在其他设备登录
+//            if (!user.getIsCanLogin()) {
+//                throw new StudyLoginException("当前登录账号在其他设备登录!", 505);
+//            }
+//            // 再次判断登录状态是否已过期
+//            if (System.currentTimeMillis() > user.getExpireTime()) {
+//                throw new StudyLoginException("登录信息已过期,请重新登录!", 504);
+//            }
+            return user;
         }
         return user;
     }
@@ -244,10 +239,8 @@
     /**
      * 设置用户身份信息
      */
-    public void setLoginUser(LoginUser loginUser)
-    {
-        if (StringUtils.isNotNull(loginUser) && StringUtils.isNotEmpty(loginUser.getToken()))
-        {
+    public void setLoginUser(LoginUser loginUser) {
+        if (StringUtils.isNotNull(loginUser) && StringUtils.isNotEmpty(loginUser.getToken())) {
             refreshToken(loginUser);
         }
     }
@@ -255,23 +248,30 @@
     /**
      * 删除用户缓存信息
      */
-    public void delLoginUser(String token)
-    {
-        if (StringUtils.isNotEmpty(token))
-        {
+    public void delLoginUser(String token) {
+        if (StringUtils.isNotEmpty(token)) {
             String userkey = JwtUtils.getUserKey(token);
             redisService.deleteObject(getTokenKey(userkey));
         }
     }
+
     /**
      * 家长端删除用户缓存信息
      */
-    public void delLoginUser1(String token)
-    {
-        if (StringUtils.isNotEmpty(token))
-        {
+    public void delLoginUser1(String token) {
+        if (StringUtils.isNotEmpty(token)) {
             String userkey = JwtUtils.getUserKey1(token);
             redisService.deleteObject(getTokenKey(userkey));
+        }
+    }
+
+    /**
+     * 学习端删除用户缓存信息
+     */
+    public void delLoginUserStudy(String token) {
+        if (StringUtils.isNotEmpty(token)) {
+            String userkey = JwtUtils.getUserKeyStudy(token);
+            redisService.deleteObject(getTokenKeyStudy(userkey));
         }
     }
 
@@ -280,27 +280,35 @@
      *
      * @param loginUser
      */
-    public void verifyToken(LoginUser loginUser)
-    {
+    public void verifyToken(LoginUser loginUser) {
         long expireTime = loginUser.getExpireTime();
         long currentTime = System.currentTimeMillis();
-        if (expireTime - currentTime <= MILLIS_MINUTE_TEN)
-        {
+        if (expireTime - currentTime <= MILLIS_MINUTE_TEN) {
             refreshToken(loginUser);
         }
     }
+
     /**
      * 验证令牌有效期,相差不足120分钟,自动刷新缓存
      *
      * @param loginUser
      */
-    public void verifyToken1(LoginUserParent loginUser)
-    {
+    public void verifyToken1(LoginUserParent loginUser) {
         long expireTime = loginUser.getExpireTime();
         long currentTime = System.currentTimeMillis();
-        if (expireTime - currentTime <= MILLIS_MINUTE_TEN)
-        {
+        if (expireTime - currentTime <= MILLIS_MINUTE_TEN) {
             refreshToken1(loginUser);
+        }
+    }
+
+    /**
+     * 验证令牌有效期,相差不足120分钟,自动刷新缓存
+     */
+    public void verifyTokenStudy(LoginUserParent loginUser) {
+        long expireTime = loginUser.getExpireTime();
+        long currentTime = System.currentTimeMillis();
+        if (expireTime - currentTime <= MILLIS_MINUTE_TEN) {
+            refreshTokenStudy(loginUser);
         }
     }
 
@@ -309,8 +317,7 @@
      *
      * @param loginUser 登录信息
      */
-    public void refreshToken(LoginUser loginUser)
-    {
+    public void refreshToken(LoginUser loginUser) {
         loginUser.setLoginTime(System.currentTimeMillis());
         loginUser.setExpireTime(loginUser.getLoginTime() + expireTime * MILLIS_MINUTE);
         // 根据uuid将loginUser缓存
@@ -321,8 +328,7 @@
     /**
      * 家长端用户登录
      */
-    public void refreshToken1(LoginUserParent dto)
-    {
+    public void refreshToken1(LoginUserParent dto) {
         dto.setLoginTime(System.currentTimeMillis());
         dto.setExpireTime(dto.getLoginTime() + expireTime * MILLIS_MINUTE);
         // 根据uuid将loginUser缓存
@@ -333,17 +339,39 @@
     /**
      * 学习端用户登录
      */
-    public void refreshTokenStudy(LoginUserParent dto)
-    {
+    public void refreshTokenStudy(LoginUserParent dto) {
+        // 获取所有 login_tokens_study: 前缀的登录缓存
+        Set redisCache = redisService.getKeysPrefix(ACCESS_TOKEN_STUDY);
+        for (Object key : redisCache) {
+            String strKey = String.valueOf(key);
+            // 根据 login_tokens:加密token 获取用户登录信息
+            Object redisCacheUserInfo = redisService.getCacheObject(strKey);
+            LoginUserParent redisUserInfo = JSONObject.parseObject(JSONObject.toJSONString(redisCacheUserInfo), LoginUserParent.class);
+            // 单点逻辑,如果当前用户已处于登录状态并再次登录,则清除该用户上一次登录token
+            if (dto.getUserid().equals(redisUserInfo.getUserid())) {
+                // 被挤账户 可登录状态 已经为 false时,跳出循环
+                if (!redisUserInfo.getIsCanLogin()) {
+                    continue;
+                }
+                // 设置能否登录字段为 否,当该token登录时,isCanLogin为false表示账号被挤
+                redisUserInfo.setIsCanLogin(Boolean.FALSE);
+                redisService.setCacheObject(strKey, redisUserInfo, redisService.getExpire(strKey), TimeUnit.SECONDS);
+            }
+        }
+        // 单点登录逻辑
         dto.setLoginTime(System.currentTimeMillis());
         dto.setExpireTime(dto.getLoginTime() + expireTime * MILLIS_MINUTE);
         // 根据uuid将loginUser缓存
-        String userKey = getTokenKey(dto.getToken());
+        String userKey = getTokenKeyStudy(dto.getToken());
         redisService.setCacheObject(userKey, dto, expireTime, TimeUnit.MINUTES);
     }
 
-    private String getTokenKey(String token)
-    {
+    private String getTokenKey(String token) {
         return ACCESS_TOKEN + token;
     }
+
+    private String getTokenKeyStudy(String token) {
+        return ACCESS_TOKEN_STUDY + token;
+    }
+
 }
\ No newline at end of file

--
Gitblit v1.7.1