From ce842703fb1d82e65635026f0ea6fc4d254dd564 Mon Sep 17 00:00:00 2001 From: hjhan Date: Tue, 24 Mar 2026 14:09:20 +0800 Subject: [PATCH] =?UTF-8?q?fix(auth):=20=E8=A7=A3=E5=86=B3=E7=99=BB?= =?UTF-8?q?=E5=BD=95=E7=99=BB=E5=87=BA=E6=B5=81=E7=A8=8B=E4=B8=AD=E7=9A=84?= =?UTF-8?q?Cookie=E7=AE=A1=E7=90=86=E5=92=8C=E4=BB=A4=E7=89=8C=E9=AA=8C?= =?UTF-8?q?=E8=AF=81=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - 在登录页面访问时记录所有Cookie信息并优化清除逻辑 - 登录处理时添加详细的请求日志记录 - 登出时先删除可能存在的旧Token避免黑名单影响 - 完善登出时的Cookie清除机制,清除所有Cookie确保安全 - 优化中间件中的令牌黑名单检查和异常处理 - 添加响应头确保浏览器正确清除缓存 - 改进日志记录的详细程度便于问题排查 --- YLErpWeb/Controllers/AccountController.cs | 40 +++++++++++++++---- YLErpWeb/Middleware/RefreshTokenMiddleware.cs | 19 ++++++--- 2 files changed, 46 insertions(+), 13 deletions(-) diff --git a/YLErpWeb/Controllers/AccountController.cs b/YLErpWeb/Controllers/AccountController.cs index 4fb4fc1a..587d43ce 100644 --- a/YLErpWeb/Controllers/AccountController.cs +++ b/YLErpWeb/Controllers/AccountController.cs @@ -36,15 +36,21 @@ namespace YLErp.Web.Controllers { var logger = LogFactory.GetLogger(); var remoteIp = HttpContext.Connection.RemoteIpAddress?.ToString(); - logger.Info($"[登录页面] 访问登录页,IP: {remoteIp}, skipSso: {skipSso}"); + + // 记录所有 Cookie + var allCookies = Request.Cookies.Select(c => $"{c.Key}={(c.Value?.Length > 10 ? c.Value?.Substring(0, 10) + "..." : c.Value)}").ToList(); + var hasAccessToken = Request.Cookies.ContainsKey("Access-Token"); + logger.Info($"[登录页面] 访问登录页,IP: {remoteIp}, skipSso: {skipSso}, HasAccessToken: {hasAccessToken}, Cookies: [{string.Join(", ", allCookies)}]"); var keys = Request.Cookies.Keys.ToArray(); + logger.Info($"[登录页面] 清除 {keys.Length} 个 Cookie(保留 {_auth_login})"); foreach (var key in keys) { if (key != _auth_login) { Response.Cookies.Delete(key); + logger.Info($"[登录页面] 删除 Cookie: {key}"); } } @@ -113,8 +119,13 @@ namespace YLErp.Web.Controllers [HttpPost, ResponseCache(NoStore = true)] public async Task LoginHandle(LogOnModel model) { + var logger = LogFactory.GetLogger(); + var hasToken = Request.Cookies.ContainsKey("Access-Token"); + logger.Info($"[登录处理] 收到登录请求 - UserName: {model?.UserName}, HasAccessToken: {hasToken}"); + if (string.IsNullOrWhiteSpace(model?.UserName) || string.IsNullOrWhiteSpace(model?.Password)) { + logger.Info("[登录处理] 用户名或密码为空"); return LoginError("用户名和密码必须填写"); } @@ -249,6 +260,10 @@ namespace YLErp.Web.Controllers await HttpContext.SignInAsync(AuthHelper.CookieAuthType, new ClaimsPrincipal(identity)); + // 先删除可能存在的旧Token(避免黑名单影响) + Response.Cookies.Delete("Access-Token"); + Response.Cookies.Delete("Access-Token-Encrypt"); + var jwtToken = AuthHelper.CreateJwtToken2(identity); Response.Cookies.Append("Access-Token", jwtToken, new CookieOptions { @@ -274,7 +289,9 @@ namespace YLErp.Web.Controllers var loginName = User.GetUserName(); var remoteIp = HttpContext.Connection.RemoteIpAddress?.ToString(); - logger.Info($"[退出登录] 用户请求退出 - UserId: {userId}, LoginName: {loginName}, IP: {remoteIp}"); + // 记录所有 Cookie + var allCookies = Request.Cookies.Select(c => $"{c.Key}={c.Value?.Substring(0, Math.Min(10, c.Value?.Length ?? 0))}...").ToList(); + logger.Info($"[退出登录] 用户请求退出 - UserId: {userId}, LoginName: {loginName}, IP: {remoteIp}, Cookies: [{string.Join(", ", allCookies)}]"); if (userId > 0) { @@ -336,10 +353,13 @@ namespace YLErp.Web.Controllers } } - // 清除 JWT Token Cookie(在加入黑名单之后) - Response.Cookies.Delete("Access-Token"); - Response.Cookies.Delete("Access-Token-Encrypt"); - logger.Info($"[退出登录] JWT Token Cookie 已清除"); + // 清除所有 Cookie(确保旧Token不会带到登录页面) + var keys = Request.Cookies.Keys.ToArray(); + foreach (var key in keys) + { + Response.Cookies.Delete(key); + } + logger.Info($"[退出登录] 所有 Cookie 已清除,共 {keys.Length} 个"); if (SsoLoginConfig.SSO_Enable) { @@ -356,7 +376,13 @@ namespace YLErp.Web.Controllers } } - logger.Info($"[退出登录] 跳转到登录页"); + logger.Info($"[退出登录] 准备重定向到登录页,清除的Cookie数量: {keys.Length}"); + + // 添加响应头,确保浏览器清除Cookie + Response.Headers.Add("Cache-Control", "no-cache, no-store, must-revalidate"); + Response.Headers.Add("Pragma", "no-cache"); + Response.Headers.Add("Expires", "0"); + return RedirectToAction("Login"); } diff --git a/YLErpWeb/Middleware/RefreshTokenMiddleware.cs b/YLErpWeb/Middleware/RefreshTokenMiddleware.cs index da37529e..f148e047 100644 --- a/YLErpWeb/Middleware/RefreshTokenMiddleware.cs +++ b/YLErpWeb/Middleware/RefreshTokenMiddleware.cs @@ -36,25 +36,32 @@ namespace YLErp.Web.Middleware { // 获取当前请求路径 var path = context.Request.Path.Value?.ToLowerInvariant() ?? ""; + var logger = LogFactory.GetLogger("RefreshTokenMiddleware"); + + // 记录请求信息 + var hasToken = context.Request.Cookies.TryGetValue("Access-Token", out var token); + var tokenPreview = hasToken && token.Length > 20 ? token.Substring(0, 20) + "..." : token; + logger.Info($"[中间件] 请求: {path}, HasToken: {hasToken}, TokenPreview: {tokenPreview}"); // 跳过登录相关页面和静态资源,避免黑名单Token影响登录流程 + // 注意:/account/login 包含 /account/loginhandle (POST登录请求) if (path.StartsWith("/account/login") || path.StartsWith("/account/logout") || path.StartsWith("/account/captcha") || - path.StartsWith("/account/sso") || - path.StartsWith("/account/callback") || + path.StartsWith("/account/callback") || // SSO回调地址 path.StartsWith("/content/") || path.StartsWith("/scripts/") || path.StartsWith("/css/") || path.StartsWith("/images/") || path.StartsWith("/favicon.ico")) { + logger.Info($"[中间件] 白名单跳过: {path}"); await _next(context); return; } - // 检查是否有Access-Token - if (context.Request.Cookies.TryGetValue("Access-Token", out var token)) + // 检查是否有Access-Token(使用已声明的token变量) + if (hasToken) { try { @@ -79,9 +86,10 @@ namespace YLErp.Web.Middleware // 检查token是否在黑名单中 var blacklisted = Server.CacheProvider.Get($"token_blacklist:{jti}"); + logger.Info($"[中间件] 黑名单检查 - JTI: {jti}, Blacklisted: {blacklisted != null}"); if (blacklisted != null) { - LogFactory.GetLogger("RefreshTokenMiddleware").Info($"[Token验证] Token已在黑名单中,拒绝访问 - JTI: {jti}"); + logger.Info($"[中间件] Token在黑名单中,拒绝访问 - JTI: {jti}, Path: {path}"); context.Response.Cookies.Delete("Access-Token"); context.Response.Cookies.Delete("Access-Token-Encrypt"); context.Response.StatusCode = 401; @@ -162,7 +170,6 @@ namespace YLErp.Web.Middleware catch (Exception ex) { // 记录其他异常 - var logger = LogFactory.GetLogger("RefreshTokenMiddleware"); logger.Error($"[Token刷新] 未知错误 - Token: {token?.Substring(0, Math.Min(20, token?.Length ?? 0))}..., 异常类型: {ex.GetType().Name}", ex); Console.WriteLine($"Token refresh error: {ex.Message}"); // 继续处理请求,不影响正常流程