This commit is contained in:
itcsx committed 2026-09-22 15:59:05 +08:00
1 parent d5d4a6f3bf
commit fb1a79a3e9
27 files changed
+708 -75

No files matched your search

@@ -447,14 +447,23 @@ namespace CloudBuilder.Security.Service
IRepository<SecurityUserWebLoginEntity> repositoryLog = service.GetRepository<IRepository<SecurityUserWebLoginEntity>>();
SecurityUserWebLoginEntity log = repositoryLog.DetachedEntities.Where(x => x.Username == username && x.SessionId == clainmName).FirstOrDefault()!;
SecurityUserWebLoginEntity log = repositoryLog.DetachedEntities.Where(x => x.Username == username && x.SessionId == clainmName).FirstOrDefault();
//不是最后登录的令牌失效
DateTime? LoginTime = repositoryLog.DetachedEntities.Where(x => x.Username == username).Max(x => x.LoginTime);
if (LoginTime.HasValue && log.LoginTime < LoginTime.Value) throw new ServiceErrorException("无效的令牌,请重新登录.");
// 先判空:原来判空写在后面,却已经先用了 log.LoginTime,
// 会话记录查不到时(日志被清理、拿了旧 token 来刷新)会抛 NullReference,
// 而不是返回友好的"无效的令牌,请重新登录."。
if (log == null) throw new ServiceErrorException("无效的令牌,请重新登录.");
if (log == null || log.RefreshToken != jwtInfo.RefreshToken || log.LogoutTime.HasValue ||
log.RefreshToken != jwtInfo.RefreshToken || log.RefreshTokenRefreshedTime.AddMinutes(Convert.ToInt32(service.CloudBuilder.CloudBuilderOptions.Jwt.RefreshExpireMins)) < DateTime.Now)
// 不是最后一次登录的令牌失效。
// 用 Any(存在更晚的登录) 代替 Max(LoginTime) 聚合:语义完全一致
// (只失效"登录时间更晚"的会话,同一时刻的并列登录依旧有效),
// 而且 Any 命中索引即可短路返回,比每次刷新都算一遍 Max 便宜。
bool hasLaterLogin = repositoryLog.DetachedEntities.Any(x => x.Username == username && x.LoginTime > log.LoginTime);
if (hasLaterLogin) throw new ServiceErrorException("无效的令牌,请重新登录.");
// 原来 RefreshToken 的比较写了两遍,去掉重复
if (log.RefreshToken != jwtInfo.RefreshToken || log.LogoutTime.HasValue ||
log.RefreshTokenRefreshedTime.AddMinutes(Convert.ToInt32(service.CloudBuilder.CloudBuilderOptions.Jwt.RefreshExpireMins)) < DateTime.Now)
throw new ServiceErrorException("无效的令牌,请重新登录.");
JwtGenerate jwtGenerate = service.ServiceProvider.GetService<JwtGenerate>()!;
@@ -470,10 +479,6 @@ namespace CloudBuilder.Security.Service
log.RefreshToken = jwtGenerate.GenerateRefreshToken();
log.RefreshTokenRefreshedTime = DateTime.Now;
if (httpContextAccessor.HttpContext.Request.Headers.ContainsKey("Authorization"))
httpContextAccessor.HttpContext.Request.Headers.Remove("Authorization");
httpContextAccessor.HttpContext.Request.Headers.Add("Authorization", "Bearer " + accessToken);
repositoryLog.UpdateNow(log);
jwtInfo.AccessToken = accessToken;