Просмотр исходного кода

!1785 连接出错时加入重试
Merge pull request !1785 from CyrusZhou/v2

zuohuaijun 10 месяцев назад
Родитель
Сommit
01679fbfa1

+ 6 - 0
Admin.NET/Admin.NET.Core/Enum/SysUserEventTypeEnum.cs

@@ -78,4 +78,10 @@ public enum SysUserEventTypeEnum
     /// </summary>
     [Description("用户退出")]
     LoginOut = 1001,
+
+    /// <summary>
+    /// RefreshToken
+    /// </summary>
+    [Description("刷新Token")]
+    RefreshToken = 1002,
 }

+ 12 - 4
Admin.NET/Admin.NET.Core/EventBus/EventConsumer.cs

@@ -54,13 +54,21 @@ public class EventConsumer<T> : IDisposable
         }
         _consumerCts = new CancellationTokenSource();
         var ct = _consumerCts.Token;
-        _consumerTask = Task.Factory.StartNew(() =>
+        _consumerTask = Task.Factory.StartNew(async () =>
         {
             while (!ct.IsCancellationRequested)
             {
-                var cr = Consumer.TakeOne(10);
-                if (cr == null) continue;
-                Received?.Invoke(this, cr);
+                try
+                {
+                    var cr = Consumer.TakeOne(10);
+                    if (cr == null) continue;
+                    Received?.Invoke(this, cr);
+                }
+                catch (Exception ex)
+                {
+                    Console.WriteLine($"消息消费异常: {ex.Message}");
+                    await Task.Delay(1000); // 短暂等待后继续尝试
+                }
             }
         }, ct, TaskCreationOptions.LongRunning, TaskScheduler.Default);
     }

+ 46 - 12
Admin.NET/Admin.NET.Core/Service/Auth/SysAuthService.cs

@@ -7,6 +7,7 @@
 using Furion.SpecificationDocument;
 using Lazy.Captcha.Core;
 using NewLife.Reflection;
+using System.Threading.Tasks;
 
 namespace Admin.NET.Core.Service;
 
@@ -224,9 +225,10 @@ public class SysAuthService : IDynamicApiController, ITransient
     /// 生成Token令牌 🔖
     /// </summary>
     /// <param name="user"></param>\
+    /// <param name="sysUserEventTypeEnum"></param>\
     /// <returns></returns>
     [NonAction]
-    internal virtual async Task<LoginOutput> CreateToken(SysUser user)
+    internal virtual async Task<LoginOutput> CreateToken(SysUser user, SysUserEventTypeEnum sysUserEventTypeEnum = SysUserEventTypeEnum.Login)
     {
         // 单用户登录
         await _sysOnlineUserService.SingleLogin(user.Id);
@@ -279,7 +281,7 @@ public class SysAuthService : IDynamicApiController, ITransient
         };
 
         // 发布系统用户操作事件
-        await _eventPublisher.PublishAsync(SysUserEventTypeEnum.Login, payload);
+        await _eventPublisher.PublishAsync(sysUserEventTypeEnum, payload);
         return payload.Output;
     }
 
@@ -329,25 +331,57 @@ public class SysAuthService : IDynamicApiController, ITransient
     /// <summary>
     /// 获取刷新Token 🔖
     /// </summary>
-    /// <param name="accessToken"></param>
-    /// <returns></returns>
+    /// <param name="accessToken">旧的AccessToken</param>
+    /// <returns>新的AccessToken和RefreshToken</returns>
     [DisplayName("获取刷新Token")]
-    public virtual string GetRefreshToken([FromQuery] string accessToken)
+    public virtual async Task<LoginOutput> GetRefreshToken([FromQuery] string accessToken)
     {
-        var refreshTokenExpire = _sysConfigService.GetRefreshTokenExpire().GetAwaiter().GetResult();
-        return JWTEncryption.GenerateRefreshToken(accessToken, refreshTokenExpire);
+        var httpContext = _httpContextAccessor.HttpContext;
+        if (httpContext == null) throw Oops.Oh(ErrorCodeEnum.D1016);
+
+        if (string.IsNullOrWhiteSpace(accessToken)) throw Oops.Oh(ErrorCodeEnum.D1011);
+
+        if (string.IsNullOrWhiteSpace(_userManager.Account)) throw Oops.Oh(ErrorCodeEnum.D1011);
+
+        // 黑名单校验
+        if (_sysCacheService.ExistKey($"blacklist:token:{accessToken}")) throw Oops.Oh(ErrorCodeEnum.D1011);
+
+        // 解析Token
+        var (isValid, tokenData, validationResult) = JWTEncryption.Validate(accessToken);
+        if (isValid) throw Oops.Oh(ErrorCodeEnum.D1016);
+
+        // 获取用户Id
+        var user = await _sysUserRep.AsQueryable().ClearFilter().FirstAsync(u => u.Id == _userManager.UserId) ?? throw Oops.Oh(ErrorCodeEnum.D1011).StatusCode(401);
+        return await CreateToken(user, SysUserEventTypeEnum.RefreshToken);
     }
 
     /// <summary>
     /// 退出系统 🔖
     /// </summary>
     [DisplayName("退出系统")]
-    public void Logout()
+    public async Task Logout()
     {
-        // 发布系统用户操作事件
-        _ = _eventPublisher.PublishAsync(SysUserEventTypeEnum.LoginOut, new { Entity = _sysUserRep.GetById(_userManager.UserId) });
-        if (string.IsNullOrWhiteSpace(_userManager.Account)) throw Oops.Oh(ErrorCodeEnum.D1011);
-        _httpContextAccessor.HttpContext.SignoutToSwagger();
+        var httpContext = _httpContextAccessor.HttpContext;
+        if (httpContext == null) throw Oops.Oh(ErrorCodeEnum.D1016);
+
+        var token = httpContext.Request.Headers["Authorization"].ToString().Replace("Bearer ", "");
+
+        if (string.IsNullOrWhiteSpace(token))
+            throw Oops.Oh(ErrorCodeEnum.D1011);
+
+        if (string.IsNullOrWhiteSpace(_userManager.Account))
+            throw Oops.Oh(ErrorCodeEnum.D1011);
+
+        // 写入黑名单(设置过期时间,避免Redis膨胀)
+        var tokenExpire = await _sysConfigService.GetTokenExpire();
+        _sysCacheService.Set($"blacklist:token:{token}", "1", TimeSpan.FromMinutes(tokenExpire));
+
+        // 发布登出事件(用户退出)
+        var user = await _sysUserRep.GetByIdAsync(_userManager.UserId);
+        await _eventPublisher.PublishAsync(SysUserEventTypeEnum.LoginOut, new { Entity = user });
+
+        // 清除 Swagger 登录信息
+        httpContext.SignoutToSwagger();
     }
 
     /// <summary>

+ 2 - 2
Admin.NET/Admin.NET.Core/Service/Common/SysCommonService.cs

@@ -45,12 +45,12 @@ public class SysCommonService : IDynamicApiController, ITransient
     public SmKeyPairOutput GetSmKeyPair()
     {
         var kp = GM.GenerateKeyPair();
-        var privateKey = Hex.ToHexString(((ECPrivateKeyParameters)kp.Private).D.ToByteArray()).ToUpper();
+        //var privateKey = Hex.ToHexString(((ECPrivateKeyParameters)kp.Private).D.ToByteArray()).ToUpper();
         var publicKey = Hex.ToHexString(((ECPublicKeyParameters)kp.Public).Q.GetEncoded()).ToUpper();
 
         return new SmKeyPairOutput
         {
-            PrivateKey = privateKey,
+            //PrivateKey = privateKey,
             PublicKey = publicKey,
         };
     }

+ 6 - 2
Admin.NET/Admin.NET.Web.Core/Handlers/JwtHandler.cs

@@ -30,8 +30,12 @@ public class JwtHandler : AppAuthorizeHandler
     /// <returns></returns>
     public override async Task HandleAsync(AuthorizationHandlerContext context, DefaultHttpContext httpContext)
     {
-        // 若当前账号存在黑名单中则授权失败
-        if (_sysCacheService.ExistKey($"{CacheConst.KeyBlacklist}{context.User.FindFirst(ClaimConst.UserId)?.Value}"))
+        var userId = context.User.FindFirst(ClaimConst.UserId)?.Value;
+        var token = httpContext.Request.Headers["Authorization"].ToString().Replace("Bearer ", "");
+
+        // 🛡️ 黑名单校验(包括用户和token)
+        if (_sysCacheService.ExistKey($"{CacheConst.KeyBlacklist}{userId}") ||
+            _sysCacheService.ExistKey($"blacklist:token:{token}"))
         {
             context.Fail();
             context.GetCurrentHttpContext().SignoutToSwagger();