From 9bbd51270710a8e104f803411499b02c6702e05f Mon Sep 17 00:00:00 2001 From: hjhan Date: Tue, 24 Mar 2026 13:04:17 +0800 Subject: [PATCH] =?UTF-8?q?fix(auth):=20=E4=BF=AE=E5=A4=8DJWT=E4=BB=A4?= =?UTF-8?q?=E7=89=8C=E7=99=BB=E5=87=BA=E5=92=8C=E5=88=B7=E6=96=B0=E4=B8=AD?= =?UTF-8?q?=E9=97=B4=E4=BB=B6=E9=97=AE=E9=A2=98=20-=20=E8=B0=83=E6=95=B4?= =?UTF-8?q?=E7=99=BB=E5=87=BA=E6=B5=81=E7=A8=8B=EF=BC=8C=E5=85=88=E5=B0=86?= =?UTF-8?q?JWT=E4=BB=A4=E7=89=8C=E5=8A=A0=E5=85=A5=E9=BB=91=E5=90=8D?= =?UTF-8?q?=E5=8D=95=E5=86=8D=E5=88=A0=E9=99=A4Cookie=20-=20=E5=9C=A8HttpH?= =?UTF-8?q?elper=E4=B8=AD=E6=B7=BB=E5=8A=A0=E7=A9=BA=E5=93=8D=E5=BA=94?= =?UTF-8?q?=E6=A3=80=E6=9F=A5=EF=BC=8C=E9=98=B2=E6=AD=A2=E6=8E=A5=E5=8F=A3?= =?UTF-8?q?=E8=BF=94=E5=9B=9E=E7=A9=BA=E5=86=85=E5=AE=B9=E6=97=B6=E5=87=BA?= =?UTF-8?q?=E9=94=99=20-=20=E5=9C=A8=E9=85=8D=E9=A2=9D=E7=9B=91=E6=8E=A7?= =?UTF-8?q?=E6=9C=8D=E5=8A=A1=E4=B8=AD=E5=A2=9E=E5=8A=A0=E5=BA=95=E5=B1=82?= =?UTF-8?q?=E7=99=BD=E5=90=8D=E5=8D=95=E6=A3=80=E6=9F=A5=E7=9A=84=E6=97=A5?= =?UTF-8?q?=E5=BF=97=E8=AE=B0=E5=BD=95=20-=20=E4=BC=98=E5=8C=96=E5=88=B7?= =?UTF-8?q?=E6=96=B0=E4=BB=A4=E7=89=8C=E4=B8=AD=E9=97=B4=E4=BB=B6=EF=BC=8C?= =?UTF-8?q?=E8=B7=B3=E8=BF=87=E7=99=BB=E5=BD=95=E7=9B=B8=E5=85=B3=E9=A1=B5?= =?UTF-8?q?=E9=9D=A2=E5=92=8C=E9=9D=99=E6=80=81=E8=B5=84=E6=BA=90=E7=9A=84?= =?UTF-8?q?=E4=BB=A4=E7=89=8C=E6=A3=80=E6=9F=A5=20-=20=E6=94=B9=E8=BF=9B?= =?UTF-8?q?=E4=BB=A4=E7=89=8C=E5=A4=B1=E6=95=88=E5=93=8D=E5=BA=94=EF=BC=8C?= =?UTF-8?q?=E8=AE=BE=E7=BD=AE=E6=AD=A3=E7=A1=AE=E7=9A=84Content-Type?= =?UTF-8?q?=E5=B9=B6=E6=8F=90=E4=BE=9B=E5=A4=9A=E8=AF=AD=E8=A8=80=E6=8F=90?= =?UTF-8?q?=E7=A4=BA=E4=BF=A1=E6=81=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Framework/YLErp.Core/Helpers/HttpHelper.cs | 7 ++++++ .../Modules/RiskModule/QuotaMonitorService.cs | 1 + YLErpWeb/Controllers/AccountController.cs | 15 +++++++------ YLErpWeb/Middleware/RefreshTokenMiddleware.cs | 22 ++++++++++++++++++- 4 files changed, 37 insertions(+), 8 deletions(-) diff --git a/Framework/YLErp.Core/Helpers/HttpHelper.cs b/Framework/YLErp.Core/Helpers/HttpHelper.cs index bbeb9b3c..460316b8 100644 --- a/Framework/YLErp.Core/Helpers/HttpHelper.cs +++ b/Framework/YLErp.Core/Helpers/HttpHelper.cs @@ -76,6 +76,13 @@ namespace YLErp.Helpers // 发送请求并响应结果 var response = await client.ExecuteAsync>(request); var responseContent = response.Content; + + // 检查响应内容是否为空 + if (string.IsNullOrEmpty(responseContent)) + { + throw new ServiceException($"接口返回为空 - URL: {_baseUrl}{apiPath}, StatusCode: {response.StatusCode}"); + } + return Newtonsoft.Json.JsonConvert.DeserializeObject(responseContent); } public async Task GetRequestNoAuth(string apiPath) diff --git a/YLErpDAL/Modules/RiskModule/QuotaMonitorService.cs b/YLErpDAL/Modules/RiskModule/QuotaMonitorService.cs index 60f833a8..0c348bc7 100644 --- a/YLErpDAL/Modules/RiskModule/QuotaMonitorService.cs +++ b/YLErpDAL/Modules/RiskModule/QuotaMonitorService.cs @@ -4970,6 +4970,7 @@ namespace YLErp.Modules.RiskModule foreach (var item in positions) { CheckUnderlyingRequest clientOrderParam = new CheckUnderlyingRequest() { clientId = clientId, securityId = item.UnderlyingCode, orderQty = item.PosiQuantity * 0.0001m, side = item.PositionType - 1 }; + _logger.Info($"[CheckUnderlyingWhiteList] 构建请求参数 - clientId: {clientId}, securityId: {item.UnderlyingCode}, orderQty: {item.PosiQuantity * 0.0001m}, side: {item.PositionType - 1}"); clientOrderParams.Add(clientOrderParam); } if (!string.IsNullOrEmpty(baseUrl) && !string.IsNullOrEmpty(checkUrl)) diff --git a/YLErpWeb/Controllers/AccountController.cs b/YLErpWeb/Controllers/AccountController.cs index e9fe8a92..4fb4fc1a 100644 --- a/YLErpWeb/Controllers/AccountController.cs +++ b/YLErpWeb/Controllers/AccountController.cs @@ -311,13 +311,9 @@ namespace YLErp.Web.Controllers HttpContext.SignOutAsync(IdentityConstants.ApplicationScheme); logger.Info($"[退出登录] SignOutAsync 已调用"); - // 清除 JWT Token Cookie - Response.Cookies.Delete("Access-Token"); - Response.Cookies.Delete("Access-Token-Encrypt"); - logger.Info($"[退出登录] JWT Token Cookie 已清除"); - - // 将当前 JWT Token 加入黑名单(使其立即失效) - if (Request.Cookies.TryGetValue("Access-Token", out var accessToken) && !string.IsNullOrEmpty(accessToken)) + // 先将当前 JWT Token 加入黑名单(使其立即失效),然后再删除 Cookie + string accessToken = null; + if (Request.Cookies.TryGetValue("Access-Token", out accessToken) && !string.IsNullOrEmpty(accessToken)) { try { @@ -340,6 +336,11 @@ namespace YLErp.Web.Controllers } } + // 清除 JWT Token Cookie(在加入黑名单之后) + Response.Cookies.Delete("Access-Token"); + Response.Cookies.Delete("Access-Token-Encrypt"); + logger.Info($"[退出登录] JWT Token Cookie 已清除"); + if (SsoLoginConfig.SSO_Enable) { switch (loginName?.ToLowerInvariant()) diff --git a/YLErpWeb/Middleware/RefreshTokenMiddleware.cs b/YLErpWeb/Middleware/RefreshTokenMiddleware.cs index 2ace3483..da37529e 100644 --- a/YLErpWeb/Middleware/RefreshTokenMiddleware.cs +++ b/YLErpWeb/Middleware/RefreshTokenMiddleware.cs @@ -34,6 +34,25 @@ namespace YLErp.Web.Middleware /// HTTP上下文 public async Task InvokeAsync(HttpContext context) { + // 获取当前请求路径 + var path = context.Request.Path.Value?.ToLowerInvariant() ?? ""; + + // 跳过登录相关页面和静态资源,避免黑名单Token影响登录流程 + if (path.StartsWith("/account/login") || + path.StartsWith("/account/logout") || + path.StartsWith("/account/captcha") || + path.StartsWith("/account/sso") || + path.StartsWith("/account/callback") || + path.StartsWith("/content/") || + path.StartsWith("/scripts/") || + path.StartsWith("/css/") || + path.StartsWith("/images/") || + path.StartsWith("/favicon.ico")) + { + await _next(context); + return; + } + // 检查是否有Access-Token if (context.Request.Cookies.TryGetValue("Access-Token", out var token)) { @@ -66,7 +85,8 @@ namespace YLErp.Web.Middleware context.Response.Cookies.Delete("Access-Token"); context.Response.Cookies.Delete("Access-Token-Encrypt"); context.Response.StatusCode = 401; - await context.Response.WriteAsync("Token已失效,请重新登录"); + context.Response.ContentType = "text/plain; charset=utf-8"; + await context.Response.WriteAsync("Token has expired / Token已失效,请重新登录 (Please go to login page / 请访问登录页面: /Account/Login)"); return; }