Seamus 3 months ago
parent
commit
4e18c32c7d
2 changed files with 42 additions and 30 deletions
  1. 2 2
      ERP.Framework/Config/SecurityConfig.cs
  2. 40 28
      ERP.Framework/Security/LoginHelper.cs

+ 2 - 2
ERP.Framework/Config/SecurityConfig.cs

@@ -40,12 +40,12 @@ namespace ERP.Framework.Config
         /// <summary>
         /// 一个设备只允许一个账号登录
         /// </summary>
-        public bool UseDeviceKey = false;
+        public bool UseDeviceKey { get; set; } = false;
 
         /// <summary>
         /// 同一账号,最大登录数量,-1代表不限
         /// </summary>
-        public int MaxLoginCount = 5;
+        public int MaxLoginCount { get; set; } = 5;
 
         public List<string>? WhiteList { get; set; }
     }

+ 40 - 28
ERP.Framework/Security/LoginHelper.cs

@@ -10,11 +10,6 @@ using ERP.Framework.Security.Core;
 using ERP.Framework.Utils;
 using Microsoft.AspNetCore.Http;
 using Newtonsoft.Json;
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
 
 namespace ERP.Framework.Security
 {
@@ -37,16 +32,16 @@ namespace ERP.Framework.Security
 
             var tokenList = GetTokenList(userInfo.UserId);
 
-            var token = TokenHelper.CreateToken(
+            var result = TokenHelper.CreateToken(
                 securityConfig.JwtSecurityKey
                 , userInfo.UserId
                 , userInfo.UserName
                 , securityConfig.TimeOut
                 , out tokenId);
 
-
             //Todo 不允许并发登录处理
-            //Todo 处理超出的会话
+
+            HandleExceedToken(tokenList, securityConfig.MaxLoginCount);
 
             tokenList.Add(new TokenSign
             {
@@ -60,11 +55,14 @@ namespace ERP.Framework.Security
 
             SetUserInfo(tokenId, userInfo, securityConfig.TimeOut);
 
-            var result = $"{FrameworkConstant.TOKEN_PREFIX} {token}";
-
             return result;
         }
 
+        /// <summary>
+        /// 获取当前用户
+        /// </summary>
+        /// <returns></returns>
+        /// <exception cref="Exception"></exception>
         public static LoginUser GetLoginUser()
         {
             var httpContextAccessor = new HttpContextAccessor();
@@ -93,6 +91,10 @@ namespace ERP.Framework.Security
             }
         }
 
+        /// <summary>
+        /// 获取当前用户Id
+        /// </summary>
+        /// <returns></returns>
         public static long? GetUserId()
         {
             var httpContextAccessor = new HttpContextAccessor();
@@ -102,7 +104,6 @@ namespace ERP.Framework.Security
             return result!.ToLong();
         }
 
-
         /// <summary>
         /// 获取TokenList缓存
         /// </summary>
@@ -114,7 +115,7 @@ namespace ERP.Framework.Security
 
             if (!tokenListData.IsNullOrEmpty())
             {
-                var data = JsonConvert.DeserializeObject<List<TokenSign>>(tokenListData);
+                var data = JsonConvert.DeserializeObject<List<TokenSign>>(tokenListData)!;
                 return data;
             }
 
@@ -126,10 +127,7 @@ namespace ERP.Framework.Security
         /// </summary>
         /// <param name="tokenId"></param>
         /// <param name="activityTimeOut"></param>
-        private static void SetLastActivity(
-            string tokenId
-            , int activityTimeOut
-            , int tokenTimeOut)
+        private static void SetLastActivity(string tokenId, int activityTimeOut, int tokenTimeOut)
         {
             var key = AuthConstant.LAST_ACTIVITY + tokenId;
             var val = DateTime.Now.AddMinutes(activityTimeOut).ToDateLongString();
@@ -137,13 +135,32 @@ namespace ERP.Framework.Security
         }
 
         /// <summary>
-        /// 退出用户
+        /// 处理超出的会话
+        /// </summary>
+        /// <param name="list"></param>
+        /// <param name="maxCount"></param>
+        private static void HandleExceedToken(List<TokenSign> list, SecurityConfig config)
+        {
+            if (list.Count > config.MaxLoginCount)
+            {
+                var num = list.Count - config.MaxLoginCount;
+                var substituteList = list.Take(num).ToList();
+
+                foreach (var item in substituteList)
+                {
+                    SubstitutedUser(item.TokenId, config.TimeOut);
+                }
+
+                list.RemoveRange(0, num);
+            }
+        }
+
+        /// <summary>
+        /// 顶下用户
         /// </summary>
         /// <param name="tokenId"></param>
         /// <param name="activityTimeOut"></param>
-        private static void LogoutUser(
-          string tokenId
-          , int tokenTimeOut)
+        private static void SubstitutedUser(string tokenId, int tokenTimeOut)
         {
             var key = AuthConstant.LAST_ACTIVITY + tokenId;
             RedisHelper.SaveExpire(key, AuthConstant.SUBSTITUTED, tokenTimeOut);
@@ -154,9 +171,7 @@ namespace ERP.Framework.Security
         /// </summary>
         /// <param name="tokenId"></param>
         /// <param name="activityTimeOut"></param>
-        private static void SetTokenList(
-            long userId
-            , List<TokenSign> list)
+        private static void SetTokenList(long userId, List<TokenSign> list)
         {
             var key = AuthConstant.TOKEN_LIST + CryptoUtil.MD5(userId.ToString());
             var val = JsonConvert.SerializeObject(list);
@@ -168,14 +183,11 @@ namespace ERP.Framework.Security
         /// </summary>
         /// <param name="tokenId"></param>
         /// <param name="activityTimeOut"></param>
-        private static void SetUserInfo(
-            string tokenId
-            , LoginUser loginUser
-            , int tokenTimeOut)
+        private static void SetUserInfo(string tokenId, LoginUser loginUser, int tokenTimeOut)
         {
             var key = AuthConstant.USER_INFO + tokenId;
             var val = JsonConvert.SerializeObject(loginUser);
             RedisHelper.SaveExpire(key, val, tokenTimeOut);
         }
     }
-}
+}