From c4f3295409142c5cdb13ff68a196694e5dcc98e5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=96=B5=E4=BD=A0=E4=B8=AA=E6=B1=AA=E5=91=80?= Date: Sun, 31 Aug 2025 20:08:47 +0800 Subject: [PATCH 1/2] =?UTF-8?q?=F0=9F=8D=92=20refactor(core):=20=E4=BD=BF?= =?UTF-8?q?=E7=94=A8=20LazyHelper=20=E7=B1=BB=E7=BB=9F=E4=B8=80=E5=A4=84?= =?UTF-8?q?=E7=90=86=E5=BB=B6=E8=BF=9F=E5=88=9D=E5=A7=8B=E5=8C=96=E6=9C=8D?= =?UTF-8?q?=E5=8A=A1=E5=AE=9E=E4=BE=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Logging/DatabaseLoggingWriter.cs | 9 +++---- .../Logging/ElasticSearchLoggingWriter.cs | 3 +-- .../Logging/HttpLoggingHandler.cs | 8 +++--- .../Service/Cache/SysCacheService.cs | 3 +-- .../Service/Common/SysCommonService.cs | 17 +++++------- .../SqlSugar/SqlSugarExtension.cs | 14 ++-------- .../SqlSugar/SqlSugarRepository.cs | 4 +-- .../Admin.NET.Core/SqlSugar/SqlSugarSetup.cs | 22 +++++++-------- Admin.NET/Admin.NET.Core/Utils/LazyHelper.cs | 23 ++++++++++++++++ .../Admin.NET.Web.Core/Handlers/JwtHandler.cs | 24 ++++++++--------- .../Service/SuperApiAop.cs | 27 +++++++++---------- 11 files changed, 78 insertions(+), 76 deletions(-) create mode 100644 Admin.NET/Admin.NET.Core/Utils/LazyHelper.cs diff --git a/Admin.NET/Admin.NET.Core/Logging/DatabaseLoggingWriter.cs b/Admin.NET/Admin.NET.Core/Logging/DatabaseLoggingWriter.cs index 21251cfe..8a30b7b6 100644 --- a/Admin.NET/Admin.NET.Core/Logging/DatabaseLoggingWriter.cs +++ b/Admin.NET/Admin.NET.Core/Logging/DatabaseLoggingWriter.cs @@ -11,8 +11,6 @@ namespace Admin.NET.Core; /// public class DatabaseLoggingWriter : IDatabaseLoggingWriter, IDisposable { - private static readonly Lazy> _sysUserRep = new(() => App.GetService>()); - private static readonly Lazy _userManager = new(() => App.GetService()); private readonly ILogger _logger; private readonly SysConfigService _sysConfigService; private readonly IEventPublisher _eventPublisher; @@ -190,6 +188,7 @@ public class DatabaseLoggingWriter : IDatabaseLoggingWriter, IDisposable /// private LoggingUserInfo GetUserInfo(LoggingMonitorDto loggingMonitor) { + var userManger = LazyHelper.GetService(); LoggingUserInfo result = new(); if (loggingMonitor.AuthorizationClaims != null) { @@ -198,7 +197,7 @@ public class DatabaseLoggingWriter : IDatabaseLoggingWriter, IDisposable .GetValueOrDefault(ClaimConst.UserId) ?? "" , out var temp) ? temp : null; - var userSession = _userManager.Value.GetSession(result.UserId); + var userSession = userManger.GetSession(result.UserId); result.TenantId = long.TryParse(userSession?.TenantId?.ToString() ?? "", out temp) ? temp : null; result.RealName = userSession?.RealName; result.Account = userSession?.Account; @@ -207,7 +206,7 @@ public class DatabaseLoggingWriter : IDatabaseLoggingWriter, IDisposable // 退出登陆时没有session,尝试从数据库中获取 if (string.IsNullOrWhiteSpace(result.Account) && result.UserId != null) { - var user = _sysUserRep.Value.GetById(result.UserId); + var user = _db.Queryable().First(u => u.Id == result.UserId); result.Account = user?.TenantId?.ToString(); result.RealName = user?.RealName; result.Account = user?.Account; @@ -221,7 +220,7 @@ public class DatabaseLoggingWriter : IDatabaseLoggingWriter, IDisposable result.Account = (loggingMonitor.Parameters[0].Value as JObject)!.GetValue("account")?.ToString(); if (!string.IsNullOrEmpty(result.Account)) { - var user = _sysUserRep.Value.AsQueryable().First(u => u.Account == result.Account); + var user = _db.Queryable().First(u => u.Account == result.Account); result.TenantId = user?.TenantId; result.RealName = user?.RealName; result.UserId = user?.Id; diff --git a/Admin.NET/Admin.NET.Core/Logging/ElasticSearchLoggingWriter.cs b/Admin.NET/Admin.NET.Core/Logging/ElasticSearchLoggingWriter.cs index 82aebef2..a39dbba8 100644 --- a/Admin.NET/Admin.NET.Core/Logging/ElasticSearchLoggingWriter.cs +++ b/Admin.NET/Admin.NET.Core/Logging/ElasticSearchLoggingWriter.cs @@ -17,7 +17,6 @@ public class ElasticSearchLoggingWriter : IDatabaseLoggingWriter, IDisposable private readonly ElasticsearchClient _esClient; private readonly SysCacheService _sysCacheService; private readonly SysConfigService _sysConfigService; - private static readonly Lazy _userManager = new(() => App.GetService()); public ElasticSearchLoggingWriter(IServiceScopeFactory scopeFactory) { @@ -51,7 +50,7 @@ public class ElasticSearchLoggingWriter : IDatabaseLoggingWriter, IDisposable { if (item.type != ClaimConst.UserId) continue; userId = item.value; - userSession = _userManager.Value?.GetSession(userId); + userSession = LazyHelper.GetService().GetSessionOrRefresh(userId); break; } tenantId = userSession?.TenantId.ToString(); diff --git a/Admin.NET/Admin.NET.Core/Logging/HttpLoggingHandler.cs b/Admin.NET/Admin.NET.Core/Logging/HttpLoggingHandler.cs index 031a2c47..1c7f7b7d 100644 --- a/Admin.NET/Admin.NET.Core/Logging/HttpLoggingHandler.cs +++ b/Admin.NET/Admin.NET.Core/Logging/HttpLoggingHandler.cs @@ -11,7 +11,6 @@ namespace Admin.NET.Core; /// public class HttpLoggingHandler : DelegatingHandler, ITransient { - private static readonly Lazy UserManager = new(() => App.GetService()); private readonly Dictionary _optionMap; private readonly SysConfigService _sysConfigService; private readonly IEventPublisher _eventPublisher; @@ -39,6 +38,7 @@ public class HttpLoggingHandler : DelegatingHandler, ITransient if (!enabledLog || attr?.IgnoreLog == true) return await base.SendAsync(request, cancellationToken); var stopWatch = Stopwatch.StartNew(); + var userManger = LazyHelper.GetService(); var urlList = request.RequestUri?.LocalPath.Split("/") ?? []; var sysLogHttp = new SysLogHttp { @@ -49,9 +49,9 @@ public class HttpLoggingHandler : DelegatingHandler, ITransient RequestUrl = request.RequestUri?.ToString(), RequestHeaders = request.Headers.ToDictionary(u => u.Key, u => u.Value.Join(";")).ToJson(), RequestBodyPlaintext = request.GetRequestBodyPlaintext(), - TenantId = UserManager.Value?.TenantId, - CreateUserId = UserManager.Value?.UserId, - CreateUserName = UserManager.Value?.RealName, + TenantId = userManger?.TenantId, + CreateUserId = userManger?.UserId, + CreateUserName = userManger?.RealName, }; if (request.Content != null) sysLogHttp.RequestBody = await request.Content.ReadAsStringAsync(cancellationToken); diff --git a/Admin.NET/Admin.NET.Core/Service/Cache/SysCacheService.cs b/Admin.NET/Admin.NET.Core/Service/Cache/SysCacheService.cs index 8dcb366f..e6165f1b 100644 --- a/Admin.NET/Admin.NET.Core/Service/Cache/SysCacheService.cs +++ b/Admin.NET/Admin.NET.Core/Service/Cache/SysCacheService.cs @@ -12,7 +12,6 @@ namespace Admin.NET.Core.Service; [ApiDescriptionSettings(Order = 400, Description = "系统缓存")] public class SysCacheService : IDynamicApiController, ISingleton { - private readonly Lazy _userManager = new(() => App.GetService()); private static ICacheProvider _cacheProvider; private readonly CacheOptions _cacheOptions; @@ -432,7 +431,7 @@ public class SysCacheService : IDynamicApiController, ISingleton public void Clear() { // 超管用户操作,清空所有缓存 - if (_userManager.Value.SuperAdmin) + if (LazyHelper.GetService().SuperAdmin) { _cacheProvider.Cache.Clear(); Cache.Default.Clear(); diff --git a/Admin.NET/Admin.NET.Core/Service/Common/SysCommonService.cs b/Admin.NET/Admin.NET.Core/Service/Common/SysCommonService.cs index a114d16a..da13eb7e 100644 --- a/Admin.NET/Admin.NET.Core/Service/Common/SysCommonService.cs +++ b/Admin.NET/Admin.NET.Core/Service/Common/SysCommonService.cs @@ -172,17 +172,14 @@ public class SysCommonService : IDynamicApiController, ITransient [DisplayName("获取所有移动端接口")] public List GetAppApiList() { - var apiList = _sysCacheService.Get>(CacheConst.KeyAppApi); - if (apiList == null) + List apiList = []; + var queue = new Queue(GetApiList()); + var item = queue.Dequeue(); + while (item != null) { - apiList = []; - var allApiList = GetApiList("", true); - foreach (var apiOutput in allApiList) - { - foreach (var controller in apiOutput.Children) - apiList.AddRange(controller.Children.Select(u => u.Route)); - } - _sysCacheService.Set(CacheConst.KeyAppApi, apiList, TimeSpan.FromDays(7)); + if (item.Children is { Count: > 0 }) queue.EnqueueRange(item.Children); + else apiList.Add(item.Route); + item = queue.Count > 0 ? queue.Dequeue() : null; } return apiList; } diff --git a/Admin.NET/Admin.NET.Core/SqlSugar/SqlSugarExtension.cs b/Admin.NET/Admin.NET.Core/SqlSugar/SqlSugarExtension.cs index f0f6f746..3d07e76e 100644 --- a/Admin.NET/Admin.NET.Core/SqlSugar/SqlSugarExtension.cs +++ b/Admin.NET/Admin.NET.Core/SqlSugar/SqlSugarExtension.cs @@ -522,11 +522,6 @@ public static class SqlSugarExtension /// private static readonly ConcurrentDictionary?> _textAbbrPropCache = new(); - /// - /// 系统通用服务 - /// - private static readonly Lazy _lazySysCommonService = new(() => App.GetService()); - /// /// 初始化文本简称数据 /// @@ -588,7 +583,7 @@ public static class SqlSugarExtension if (string.IsNullOrWhiteSpace(value)) return; // 使用线程安全的延迟初始化服务实例获取文本缩写 - var abbrValue = _lazySysCommonService.Value + var abbrValue = LazyHelper.GetService() .GetNameAbbr(new() { Text = value, All = attribute.SaveFullAbbr }) .GetAwaiter() .GetResult(); @@ -604,11 +599,6 @@ public static class SqlSugarExtension /// private static readonly ConcurrentDictionary?> _serialPropCache = new(); - /// - /// 系统通用服务 - /// - private static readonly Lazy _lazySysSerialService = new(() => App.GetService()); - /// /// 自动生成流水号到绑定字段 /// @@ -643,7 +633,7 @@ public static class SqlSugarExtension var (_, attribute) = propData; // 使用线程安全的延迟初始化服务实例获取流水号 - var serial = _lazySysSerialService.Value + var serial = LazyHelper.GetService() .NextSeqNo(attribute.Type, attribute.IsGlobal) .GetAwaiter() .GetResult(); diff --git a/Admin.NET/Admin.NET.Core/SqlSugar/SqlSugarRepository.cs b/Admin.NET/Admin.NET.Core/SqlSugar/SqlSugarRepository.cs index 17bf27bc..8eb2525b 100644 --- a/Admin.NET/Admin.NET.Core/SqlSugar/SqlSugarRepository.cs +++ b/Admin.NET/Admin.NET.Core/SqlSugar/SqlSugarRepository.cs @@ -12,8 +12,6 @@ namespace Admin.NET.Core; /// public class SqlSugarRepository : SimpleClient, ISqlSugarRepository where T : class, new() { - private static readonly Lazy _userManager = new(() => App.GetService()); - public SqlSugarRepository() { var iTenant = SqlSugarSetup.ITenant; @@ -39,7 +37,7 @@ public class SqlSugarRepository : SimpleClient, ISqlSugarRepository whe return; // 若未贴任何表特性或当前未登录或是默认租户Id,则返回默认库连接 - var tenantId = _userManager.Value.TenantId?.ToString(); + var tenantId = LazyHelper.GetService().TenantId?.ToString(); if (string.IsNullOrWhiteSpace(tenantId) || tenantId == SqlSugarConst.MainConfigId) return; // 根据租户Id切换库连接, 为空则返回默认库连接 diff --git a/Admin.NET/Admin.NET.Core/SqlSugar/SqlSugarSetup.cs b/Admin.NET/Admin.NET.Core/SqlSugar/SqlSugarSetup.cs index 19326482..133bd038 100644 --- a/Admin.NET/Admin.NET.Core/SqlSugar/SqlSugarSetup.cs +++ b/Admin.NET/Admin.NET.Core/SqlSugar/SqlSugarSetup.cs @@ -215,8 +215,8 @@ public static class SqlSugarSetup Log.Warning(log); }; + var userManager = LazyHelper.GetService(); // 数据审计 - Lazy userManager = new(() => App.GetService()); dbProvider.Aop.DataExecuting = (oldValue, entityInfo) => { // 新增/插入 操作 @@ -249,7 +249,7 @@ public static class SqlSugarSetup } // 若当前用户非空(web线程时) - if (App.User == null || userManager.Value == null) return; + if (App.User == null) return; dynamic entityValue = entityInfo.EntityValue; // 若应用Id为空则赋值当前用户应用Id,若当前用户应用Id为空,则取默认应用Id @@ -257,33 +257,33 @@ public static class SqlSugarSetup { var appId = entityInfo.EntityColumnInfo.PropertyInfo.GetValue(entityInfo.EntityValue)!; if (appId == null || appId.Equals(0)) - entityInfo.SetValue(userManager.Value?.AppId ?? SqlSugarConst.DefaultAppId); + entityInfo.SetValue(userManager.AppId ?? SqlSugarConst.DefaultAppId); } else if (entityInfo.PropertyName == nameof(EntityTenantId.TenantId)) { if (entityValue.TenantId == null || entityValue.TenantId == 0) - entityInfo.SetValue(userManager.Value.TenantId?.ToString() ?? + entityInfo.SetValue(userManager.TenantId?.ToString() ?? SqlSugarConst.DefaultTenantId.ToString()); } else if (entityInfo.PropertyName == nameof(EntityBase.CreateUserId)) { if (entityValue.CreateUserId == null || entityValue.CreateUserId == 0) - entityInfo.SetValue(userManager.Value.UserId); + entityInfo.SetValue(userManager.UserId); } else if (entityInfo.PropertyName == nameof(EntityBase.CreateUserName)) { if (string.IsNullOrWhiteSpace(entityValue.CreateUserName)) - entityInfo.SetValue(userManager.Value.RealName); + entityInfo.SetValue(userManager.RealName); } else if (entityInfo.PropertyName == nameof(EntityBaseData.CreateOrgId)) { if (entityValue.CreateOrgId == null || entityValue.CreateOrgId == 0) - entityInfo.SetValue(userManager.Value.OrgId); + entityInfo.SetValue(userManager.OrgId); } else if (entityInfo.PropertyName == nameof(EntityBaseData.CreateOrgName)) { if (string.IsNullOrWhiteSpace(entityValue.CreateOrgName)) - entityInfo.SetValue(userManager.Value.OrgName); + entityInfo.SetValue(userManager.OrgName); } } // 编辑/更新 操作 @@ -294,7 +294,7 @@ public static class SqlSugarSetup else if (entityInfo.PropertyName == nameof(EntityBase.UpdateUserId)) entityInfo.SetValue(App.User?.FindFirst(ClaimConst.UserId)?.Value); else if (entityInfo.PropertyName == nameof(EntityBase.UpdateUserName)) - entityInfo.SetValue(userManager.Value.RealName); + entityInfo.SetValue(userManager.RealName); } // 设置绑定简称字段数据 @@ -308,13 +308,13 @@ public static class SqlSugarSetup }; // 超管不受任何过滤器限制 - if (userManager.Value.AccountType == AccountTypeEnum.SuperAdmin) return; + if (userManager.AccountType == AccountTypeEnum.SuperAdmin) return; // 配置假删除过滤器 dbProvider.QueryFilter.AddTableFilter(u => u.IsDelete == false); // 配置租户过滤器 - var tenantId = userManager.Value.TenantId?.ToString(); + var tenantId = userManager.TenantId?.ToString(); if (!string.IsNullOrWhiteSpace(tenantId)) dbProvider.QueryFilter.AddTableFilter(u => u.TenantId == long.Parse(tenantId)); diff --git a/Admin.NET/Admin.NET.Core/Utils/LazyHelper.cs b/Admin.NET/Admin.NET.Core/Utils/LazyHelper.cs new file mode 100644 index 00000000..0c9ec2d5 --- /dev/null +++ b/Admin.NET/Admin.NET.Core/Utils/LazyHelper.cs @@ -0,0 +1,23 @@ +// Admin.NET 项目的版权、商标、专利和其他相关权利均受相应法律法规的保护。使用本项目应遵守相关法律法规和许可证的要求。 +// +// 本项目主要遵循 MIT 许可证和 Apache 许可证(版本 2.0)进行分发和使用。许可证位于源代码树根目录中的 LICENSE-MIT 和 LICENSE-APACHE 文件。 +// +// 不得利用本项目从事危害国家安全、扰乱社会秩序、侵犯他人合法权益等法律法规禁止的活动!任何基于本项目二次开发而产生的一切法律纠纷和责任,我们不承担任何责任! + +namespace Admin.NET.Core; + +public class LazyHelper +{ + private static readonly Dictionary> _cache = new(); + + /// + /// 获取服务 + /// + /// + /// + public static T GetService() where T : class + { + if (_cache.TryGetValue(typeof(T), out var lazy)) return (T)lazy.Value; + return (T)(_cache[typeof(T)] = new Lazy(() => App.GetService())).Value; + } +} \ No newline at end of file diff --git a/Admin.NET/Admin.NET.Web.Core/Handlers/JwtHandler.cs b/Admin.NET/Admin.NET.Web.Core/Handlers/JwtHandler.cs index bc5fef16..11cdef53 100644 --- a/Admin.NET/Admin.NET.Web.Core/Handlers/JwtHandler.cs +++ b/Admin.NET/Admin.NET.Web.Core/Handlers/JwtHandler.cs @@ -23,7 +23,6 @@ namespace Admin.NET.Web.Core public class JwtHandler : AppAuthorizeHandler { private readonly IServiceProvider _serviceProvider; - private static readonly Lazy _userManager = new(() => App.GetService()); public JwtHandler(IServiceProvider serviceProvider) { @@ -93,7 +92,7 @@ namespace Admin.NET.Web.Core } // 验证租户有效期 - var tenantId = _userManager.Value.TenantId?.ToString(); + var tenantId = LazyHelper.GetService().TenantId?.ToString(); if (!string.IsNullOrWhiteSpace(tenantId)) { var tenant = sysCacheService.Get>(CacheConst.KeyTenant)?.FirstOrDefault(u => u.Id == long.Parse(tenantId)); @@ -119,32 +118,31 @@ namespace Admin.NET.Web.Core /// private static async Task CheckAuthorizeAsync(DefaultHttpContext httpContext) { - // 排除超管权限判断 - if (_userManager.Value?.AccountType == AccountTypeEnum.SuperAdmin) - return true; + var userManager = LazyHelper.GetService(); - var serviceScope = httpContext.RequestServices.CreateScope(); + // 排除超管权限判断 + if (userManager?.AccountType == AccountTypeEnum.SuperAdmin) return true; // 当前接口路由 var path = httpContext.Request.Path.ToString(); // 移动端接口权限判断 - if (_userManager.Value?.LoginMode == LoginModeEnum.APP) + if (userManager?.LoginMode == LoginModeEnum.APP) { - var appApiList = serviceScope.ServiceProvider.GetRequiredService().GetAppApiList(); - return appApiList.Exists(u => path.EndsWith(u, StringComparison.CurrentCultureIgnoreCase)); + var appPermissions = userManager.AppPermissions ?? []; + return appPermissions.Exists(u => path.EndsWith(u, StringComparison.CurrentCultureIgnoreCase)); } // 获取当前用户按钮权限集合和接口黑名单 - var sysRoleService = serviceScope.ServiceProvider.GetRequiredService(); - var roleApis = await sysRoleService.GetUserApiList(); + var unauthorizedPermissions = userManager?.UnauthorizedPermissions ?? []; + var permissions = userManager?.Permissions ?? []; // 若当前路由在按钮权限集合里面则放行 - if (roleApis[0].Exists(u => path.EndsWith(u, StringComparison.CurrentCultureIgnoreCase))) + if (permissions.Exists(u => path.EndsWith(u, StringComparison.CurrentCultureIgnoreCase))) return true; // 若当前路由在已接口黑名单里面则禁止 - return roleApis[1].TrueForAll(u => !path.EndsWith(u, StringComparison.CurrentCultureIgnoreCase)); + return unauthorizedPermissions.TrueForAll(u => !path.EndsWith(u, StringComparison.CurrentCultureIgnoreCase)); } } } \ No newline at end of file diff --git a/Admin.NET/Plugins/Admin.NET.Plugin.ReZero/Service/SuperApiAop.cs b/Admin.NET/Plugins/Admin.NET.Plugin.ReZero/Service/SuperApiAop.cs index 33b4e7b2..f3ddb0eb 100644 --- a/Admin.NET/Plugins/Admin.NET.Plugin.ReZero/Service/SuperApiAop.cs +++ b/Admin.NET/Plugins/Admin.NET.Plugin.ReZero/Service/SuperApiAop.cs @@ -17,8 +17,6 @@ namespace Admin.NET.Plugin.ReZero.Service; /// public class SuperApiAop : DefaultSuperApiAop { - private static readonly Lazy _userManager = new(() => App.GetService()); - public override async Task OnExecutingAsync(InterfaceContext aopContext) { ////if (aopContext.InterfaceType == InterfaceType.DynamicApi) @@ -60,33 +58,34 @@ public class SuperApiAop : DefaultSuperApiAop var api = aopContext.InterfaceInfo; var context = aopContext.HttpContext; - var paths = api.Url.Split('/'); - var actionName = paths[paths.Length - 1]; + var paths = api?.Url?.Split('/'); + var actionName = paths?[^1]; + var userManager = LazyHelper.GetService(); var apiInfo = new { - requestUrl = api.Url, - httpMethod = api.HttpMethod, - displayTitle = api.Name, + requestUrl = api?.Url, + httpMethod = api?.HttpMethod, + displayTitle = api?.Name, actionTypeName = actionName, - controllerName = aopContext.InterfaceType == InterfaceType.DynamicApi ? $"ReZero动态-{api.GroupName}" : $"ReZero系统-{api.GroupName}", + controllerName = aopContext.InterfaceType == InterfaceType.DynamicApi ? $"ReZero动态-{api?.GroupName}" : $"ReZero系统-{api?.GroupName}", remoteIPv4 = context.GetRemoteIpAddressToIPv4(), - userAgent = context.Request.Headers["User-Agent"], + userAgent = context?.Request.Headers["User-Agent"], returnInformation = new { - httpStatusCode = context.Response.StatusCode, + httpStatusCode = context?.Response.StatusCode, }, authorizationClaims = new[] { new { - type = _userManager.Value?.Account, - value = _userManager.Value?.RealName + type = userManager?.Account, + value = userManager?.RealName }, new { - type = _userManager.Value?.RealName, - value = _userManager.Value?.RealName + type = userManager?.RealName, + value = userManager?.RealName }, }, exception = aopContext.Exception == null ? null : JSON.Serialize(aopContext.Exception) From ef5852ea892fc07752915668e117eda5d7cc8dba Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=96=B5=E4=BD=A0=E4=B8=AA=E6=B1=AA=E5=91=80?= Date: Sun, 31 Aug 2025 20:24:51 +0800 Subject: [PATCH 2/2] =?UTF-8?q?=F0=9F=8D=92=20feat:=20=E5=A2=9E=E5=BC=BAse?= =?UTF-8?q?ssion=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../Service/App/Auth/AppAuthService.cs | 6 +- .../Service/Auth/SysAuthService.cs | 119 +++++++++++------- .../Service/CodeGen/SysCodeGenService.cs | 5 +- .../Service/Role/SysRoleService.cs | 89 +++++++------ .../Service/User/SysUserRoleService.cs | 8 +- .../Service/User/UserManager.cs | 80 +++++++++++- .../Service/User/UserSessionDao.cs | 64 +++++++++- .../Admin.NET.Core/SqlSugar/SqlSugarFilter.cs | 45 +++---- .../Admin.NET.Web.Core/Handlers/JwtHandler.cs | 2 +- 9 files changed, 290 insertions(+), 128 deletions(-) diff --git a/Admin.NET/Admin.NET.Application/Service/App/Auth/AppAuthService.cs b/Admin.NET/Admin.NET.Application/Service/App/Auth/AppAuthService.cs index ce839f15..c5f79ecd 100644 --- a/Admin.NET/Admin.NET.Application/Service/App/Auth/AppAuthService.cs +++ b/Admin.NET/Admin.NET.Application/Service/App/Auth/AppAuthService.cs @@ -171,8 +171,6 @@ public class AppAuthService : IDynamicApiController, ITransient .LeftJoin((u, a) => u.RoleId == a.Id) .Where(u => u.UserId == user.Id) .Select((u, a) => new RoleDto { Id = a.Id, Name = a.Name, Code = a.Code }).ToListAsync(); - // 接口集合 - var apis = (await _sysRoleService.GetUserApiList())[0]; return new LoginUserOutput { @@ -190,8 +188,8 @@ public class AppAuthService : IDynamicApiController, ITransient OrgName = org?.Name, OrgType = org?.Type, PosName = pos?.Name, - Apis = apis, - Roles = roles + Roles = roles, + Apis = _appUserManager.Permissions, }; } diff --git a/Admin.NET/Admin.NET.Core/Service/Auth/SysAuthService.cs b/Admin.NET/Admin.NET.Core/Service/Auth/SysAuthService.cs index dc4c0348..5e969cc7 100644 --- a/Admin.NET/Admin.NET.Core/Service/Auth/SysAuthService.cs +++ b/Admin.NET/Admin.NET.Core/Service/Auth/SysAuthService.cs @@ -221,16 +221,15 @@ public class SysAuthService : IDynamicApiController, ITransient /// /// /// - /// /// [NonAction] - public async Task CreateToken(SysUser user, LoginModeEnum loginMode = LoginModeEnum.PC, bool isRefresh = false) + public async Task CreateToken(SysUser user, LoginModeEnum loginMode = LoginModeEnum.PC) { // 单用户登录 await App.GetRequiredService().SingleLogin(user.Id, loginMode); // 生成Token令牌 - if(!isRefresh) user.TokenVersion += 1; + user.TokenVersion += 1; var tokenExpire = await _sysConfigService.GetTokenExpire(); var accessToken = JWTEncryption.Encrypt(new Dictionary { @@ -238,24 +237,6 @@ public class SysAuthService : IDynamicApiController, ITransient { ClaimConst.TokenVersion, user.TokenVersion }, }, tokenExpire); - // 缓存用户Session - _userManager.SetSession(new() - { - UserId = user.Id, - TenantId = user.TenantId, - Account = user.Account, - RealName = user.RealName, - AccountType = user.AccountType, - OrgId = user.OrgId, - OrgCode = user.SysOrg?.Code, - OrgName = user.SysOrg?.Name, - OrgType = user.SysOrg?.Type, - OrgLevel = user.SysOrg?.Level, - LoginMode = loginMode, - TokenVersion = user.TokenVersion, - ExtProps = App.GetServices().SelectMany(u => u.GetInitExtProps(user)).ToDictionary(u => u.Key, u => u.Value) - }, TimeSpan.FromMinutes(tokenExpire)); - // 生成刷新Token令牌 var refreshTokenExpire = await _sysConfigService.GetRefreshTokenExpire(); var refreshToken = JWTEncryption.GenerateRefreshToken(accessToken, refreshTokenExpire); @@ -267,27 +248,27 @@ public class SysAuthService : IDynamicApiController, ITransient // ke.global.setAllHeader('Authorization', 'Bearer ' + ke.response.headers['access-token']); // 更新用户登录信息 - if (!isRefresh) + user.LastLoginIp = _httpContextAccessor.HttpContext.GetRemoteIpAddressToIPv4(true); + (user.LastLoginAddress, double? longitude, double? latitude) = CommonHelper.GetIpAddress(user.LastLoginIp); + user.LastLoginTime = DateTime.Now; + user.LastLoginDevice = CommonHelper.GetClientDeviceInfo(_httpContextAccessor.HttpContext?.Request?.Headers?.UserAgent); + await _sysUserRep.AsUpdateable(user).UpdateColumns(u => new { - user.LastLoginIp = _httpContextAccessor.HttpContext.GetRemoteIpAddressToIPv4(true); - (user.LastLoginAddress, double? longitude, double? latitude) = CommonHelper.GetIpAddress(user.LastLoginIp); - user.LastLoginTime = DateTime.Now; - user.LastLoginDevice = CommonHelper.GetClientDeviceInfo(_httpContextAccessor.HttpContext?.Request?.Headers?.UserAgent); - await _sysUserRep.AsUpdateable(user).UpdateColumns(u => new - { - u.TokenVersion, - u.LastLoginIp, - u.LastLoginAddress, - u.LastLoginTime, - u.LastLoginDevice, - }).ExecuteCommandAsync(); + u.TokenVersion, + u.LastLoginIp, + u.LastLoginAddress, + u.LastLoginTime, + u.LastLoginDevice, + }).ExecuteCommandAsync(); - // 缓存用户Token版本 - _sysCacheService.Set($"{CacheConst.KeyUserToken}{user.Id}", $"{user.TokenVersion}"); + // 缓存用户Token版本 + _sysCacheService.Set($"{CacheConst.KeyUserToken}{user.Id}", $"{user.TokenVersion}"); - // 发布系统登录事件 - await _eventPublisher.PublishAsync(UserEventTypeEnum.Login, user); - } + // 发布系统登录事件 + await _eventPublisher.PublishAsync(UserEventTypeEnum.Login, user); + + // 缓存用户Session + await SetUserSession(user, loginMode); return new LoginOutput { @@ -296,6 +277,56 @@ public class SysAuthService : IDynamicApiController, ITransient }; } + /// + /// 设置用户Session + /// + /// + /// + private async Task SetUserSession(SysUser user, LoginModeEnum loginMode = LoginModeEnum.PC) + { + var db = _sysUserRep.Context.CopyNew(); + user.SysPos ??= await db.Queryable().FirstAsync(u => u.Id == user.PosId); + user.SysOrg ??= await db.Queryable().FirstAsync(u => u.Id == user.OrgId); + + var permissions = await LazyHelper.GetService().GetUserApiList(user.Id); + var unauthorizedPermissions = await LazyHelper.GetService().GetUnAuthApiList(user.Id); + var orgIds = await LazyHelper.GetService().GetUserOrgIdList(user.Id, user.OrgId); + var roleIds = await db.Queryable().Where(u => u.UserId == user.Id).Select(u => u.RoleId).ToListAsync(); + var postIds = await db.Queryable().Where(u => u.UserId == user.Id).Select(u => u.PosId).ToListAsync() ?? []; + var maxDataScope = await db.Queryable().Where(u => roleIds.Contains(u.Id)).MinAsync(u => u.DataScope); + if (maxDataScope == 0) maxDataScope = DataScopeEnum.Self; + postIds.Add(user.PosId); + + // 缓存用户Session + _userManager.SetSession(new() + { + UserId = user.Id, + TenantId = user.TenantId, + Account = user.Account, + RealName = user.RealName, + NickName = user.NickName, + AccountType = user.AccountType, + OrgId = user.OrgId, + OrgCode = user.SysOrg?.Code, + OrgName = user.SysOrg?.Name, + OrgType = user.SysOrg?.Type, + OrgLevel = user.SysOrg?.Level, + PosId = user.PosId, + PosName = user.SysPos?.Name, + PosCode = user.SysPos?.Code, + LoginMode = loginMode, + TokenVersion = user.TokenVersion, + OrgIds = orgIds, + PosIds = postIds, + RoleIds = roleIds, + Permissions = permissions, + UnauthorizedPermissions = unauthorizedPermissions, + AppPermissions = loginMode == LoginModeEnum.APP ? LazyHelper.GetService().GetAppApiList() : null, + MaxDataScope = user.AccountType == AccountTypeEnum.SuperAdmin ? DataScopeEnum.All : maxDataScope, + ExtProps = App.GetServices().SelectMany(u => u.GetInitExtProps(user)).ToDictionary(u => u.Key, u => u.Value) + }); + } + /// /// 获取当前登陆用户信息 🔖 /// @@ -313,8 +344,6 @@ public class SysAuthService : IDynamicApiController, ITransient .LeftJoin((u, a) => u.RoleId == a.Id) .Where(u => u.UserId == user.Id) .Select((u, a) => new RoleDto { Id = a.Id, Name = a.Name, Code = a.Code }).ToListAsync(); - // 接口集合 - var apis = (await App.GetRequiredService().GetUserApiList())[0]; // 个性化水印文字(若系统水印为空则不显示) var watermarkText = await _sysUserRep.ChangeRepository>().AsQueryable().Where(u => u.Id == user.TenantId).Select(u => u.Watermark).FirstAsync(); if (!string.IsNullOrWhiteSpace(watermarkText)) @@ -337,7 +366,7 @@ public class SysAuthService : IDynamicApiController, ITransient OrgName = org?.Name, OrgType = org?.Type, PosName = pos?.Name, - Apis = apis, + Apis = _userManager.Permissions, Roles = roles, WatermarkText = watermarkText, LastChangePasswordTime = user.LastChangePasswordTime @@ -447,13 +476,13 @@ public class SysAuthService : IDynamicApiController, ITransient } /// - /// 刷新token + /// 刷新Session /// /// [NonAction] - public async Task RefreshToken(long userId) + public async Task RefreshSession(long userId) { var user = await _sysUserRep.AsQueryable().IgnoreTenant().Includes(u => u.SysOrg).FirstAsync(u => u.Id == userId); - await CreateToken(user, CommonHelper.IsMobile(_httpContextAccessor.HttpContext?.Request.Headers.UserAgent ?? "") ? LoginModeEnum.APP : LoginModeEnum.PC, true); + await SetUserSession(user, CommonHelper.IsMobile(_httpContextAccessor.HttpContext?.Request.Headers.UserAgent ?? "") ? LoginModeEnum.APP : LoginModeEnum.PC); } } \ No newline at end of file diff --git a/Admin.NET/Admin.NET.Core/Service/CodeGen/SysCodeGenService.cs b/Admin.NET/Admin.NET.Core/Service/CodeGen/SysCodeGenService.cs index a8d89ffe..3580f8e6 100644 --- a/Admin.NET/Admin.NET.Core/Service/CodeGen/SysCodeGenService.cs +++ b/Admin.NET/Admin.NET.Core/Service/CodeGen/SysCodeGenService.cs @@ -17,6 +17,7 @@ public class SysCodeGenService : IDynamicApiController, ITransient { private readonly ISqlSugarClient _db; private readonly CodeGenOptions _codeGenOptions; + private readonly SysCacheService _sysCacheService; private readonly DbConnectionOptions _dbConnectionOptions; private readonly SysCodeGenConfigService _codeGenConfigService; private readonly IViewEngine _viewEngine; @@ -25,12 +26,14 @@ public class SysCodeGenService : IDynamicApiController, ITransient IOptions codeGenOptions, IOptions dbConnectionOptions, SysCodeGenConfigService codeGenConfigService, + SysCacheService sysCacheService, IViewEngine viewEngine) { _db = db; _dbConnectionOptions = dbConnectionOptions.Value; _codeGenOptions = codeGenOptions.Value; _codeGenConfigService = codeGenConfigService; + _sysCacheService = sysCacheService; _viewEngine = viewEngine; } @@ -600,7 +603,7 @@ public class SysCodeGenService : IDynamicApiController, ITransient await _db.Insertable(menus).ExecuteCommandAsync(); // 删除角色菜单按钮缓存 - App.GetRequiredService().RemoveByPrefixKey(CacheConst.KeyUserApi); + _sysCacheService.RemoveByPrefixKey(CacheConst.KeyUserSession); } /// diff --git a/Admin.NET/Admin.NET.Core/Service/Role/SysRoleService.cs b/Admin.NET/Admin.NET.Core/Service/Role/SysRoleService.cs index db8ce7a3..ec436def 100644 --- a/Admin.NET/Admin.NET.Core/Service/Role/SysRoleService.cs +++ b/Admin.NET/Admin.NET.Core/Service/Role/SysRoleService.cs @@ -395,56 +395,67 @@ public class SysRoleService : IDynamicApiController, ITransient //return roleApis.Union(roleButtons).ToList(); } + /// - /// 获取用户接口集合 🔖 + /// 获取用户接口集合 /// + /// /// - [DisplayName("获取用户接口集合")] - public async Task>> GetUserApiList() + [NonAction] + public async Task> GetUserApiList(long userId) { - var userId = _userManager.UserId; - var apiList = _sysCacheService.Get>>(CacheConst.KeyUserApi + userId); - if (apiList != null) return apiList; - - apiList = [[], []]; - // 所有按钮权限集合 - var allButtonList = await GetButtonList(); + List apiList = []; // 超管账号获取所有接口 - if (_userManager.SuperAdmin) + if (await _sysRoleRep.Context.Queryable().IgnoreTenant().AnyAsync(u => u.Id == userId && u.AccountType == AccountTypeEnum.SuperAdmin)) { - var allApiList = _sysCommonService.GetApiList(); - foreach (var apiOutput in allApiList) + // 获取所有接口 + var queue = new Queue(_sysCommonService.GetApiList()); + var item = queue.Dequeue(); + while (item != null) { - foreach (var controller in apiOutput.Children) - apiList[0].AddRange(controller.Children.Select(u => u.Route)); + if (item.Children is { Count: > 0 }) queue.EnqueueRange(item.Children); + else apiList.Add(item.Route); + item = queue.Count > 0 ? queue.Dequeue() : null; } - - // 接口没有对应的按钮权限集合 - var diffButtonList = allButtonList.Except(apiList[0]).ToList(); // 差集 - apiList[0].AddRange(diffButtonList); } else { - // 当前账号所有角色集合 - var roleIdList = await _sysUserRoleService.GetUserRoleIdList(_userManager.UserId); - // 已有按钮权限集合 - var menuIdList = await _sysRoleMenuService.GetRoleMenuIdList(roleIdList); - apiList[0] = await GetButtonList(menuIdList, false); - - // 未有按钮权限集合(放到接口黑名单里面) - apiList[1] = allButtonList.Except(apiList[0]).ToList(); // 差集 - // 接口黑名单集合 - var roleApiList = await _sysRoleApiService.GetRoleApiList(roleIdList); - apiList[1].AddRange(roleApiList); + // 获取账号所有权限集 + var menuIdList = await _sysRoleMenuService.GetRoleMenuIdList(await _sysUserRoleService.GetUserRoleIdList(userId)); + apiList = await GetButtonList(menuIdList, false); } - - // 排序接口名称 - apiList[0].Sort(); - apiList[1].Sort(); - _sysCacheService.Set(CacheConst.KeyUserApi + userId, apiList, TimeSpan.FromDays(7)); // 缓存7天 + apiList = apiList.Distinct().ToList(); + apiList.Sort(); return apiList; } + /// + /// 获取无权访问接口集合 🔖 + /// + [NonAction] + public async Task> GetUnAuthApiList(long userId) + { + if (await _sysRoleRep.Context.Queryable().IgnoreTenant().AnyAsync(u => u.Id == userId && u.AccountType == AccountTypeEnum.SuperAdmin)) return []; + + // 所有按钮权限集合 + var allButtonList = await GetButtonList(); + + // 当前账号所有角色集合 + var roleIds = await _sysUserRoleService.GetUserRoleIdList(userId); + + // 菜单中已有的权限集与当前用户的权限集差集,就是无权访问的权限集 + var menuIdList = await _sysRoleMenuService.GetRoleMenuIdList(roleIds); + var apiList = await GetButtonList(menuIdList, false); + var blackList = allButtonList.Except(apiList).ToList(); // 差集 + + // 角色接口黑名单集合 + blackList.AddRange(await _sysRoleApiService.GetRoleApiList(roleIds)); + blackList = blackList.Distinct().ToList(); + + blackList.Sort(); + return blackList; + } + ///// ///// 获取用户按钮权限集合 ///// @@ -485,7 +496,8 @@ public class SysRoleService : IDynamicApiController, ITransient .WhereIF(menuIds != null && menuIds.Count > 0, u => menuIds.Contains(u.Id)) .WhereIF(!isAll, u => u.Status == StatusEnum.Enable) .Where(u => u.Type == MenuTypeEnum.Btn) - .Select(u => u.Permission).ToListAsync(); + .Select(u => u.Permission) + .ToListAsync(); } /// @@ -497,9 +509,6 @@ public class SysRoleService : IDynamicApiController, ITransient public async Task ClearUserApiCache(long roleId) { var userIdList = await _sysUserRoleService.GetUserIdList(roleId); - foreach (var userId in userIdList) - { - _sysCacheService.Remove(CacheConst.KeyUserApi + userId); - } + foreach (var userId in userIdList) _sysCacheService.Remove(CacheConst.KeyUserSession + userId); } } \ No newline at end of file diff --git a/Admin.NET/Admin.NET.Core/Service/User/SysUserRoleService.cs b/Admin.NET/Admin.NET.Core/Service/User/SysUserRoleService.cs index c2216355..06a94480 100644 --- a/Admin.NET/Admin.NET.Core/Service/User/SysUserRoleService.cs +++ b/Admin.NET/Admin.NET.Core/Service/User/SysUserRoleService.cs @@ -39,7 +39,7 @@ public class SysUserRoleService : ITransient await _sysUserRoleRep.InsertRangeAsync(userRoles); // 清除缓存 - _sysCacheService.Remove(CacheConst.KeyUserApi + input.UserId); + _sysCacheService.Remove(CacheConst.KeyUserSession + input.UserId); } /// @@ -61,7 +61,7 @@ public class SysUserRoleService : ITransient // 清除缓存 foreach (var userId in input.UserIdList) { - _sysCacheService.Remove(CacheConst.KeyUserApi + userId); + _sysCacheService.Remove(CacheConst.KeyUserSession + userId); } } @@ -80,7 +80,7 @@ public class SysUserRoleService : ITransient // 清除缓存 foreach (var userId in userIdList) { - _sysCacheService.Remove(CacheConst.KeyUserApi + userId); + _sysCacheService.Remove(CacheConst.KeyUserSession + userId); } await _sysUserRoleRep.DeleteAsync(u => u.RoleId == roleId); @@ -96,7 +96,7 @@ public class SysUserRoleService : ITransient await _sysUserRoleRep.DeleteAsync(u => u.UserId == userId); // 清除缓存 - _sysCacheService.Remove(CacheConst.KeyUserApi + userId); + _sysCacheService.Remove(CacheConst.KeyUserSession + userId); } /// diff --git a/Admin.NET/Admin.NET.Core/Service/User/UserManager.cs b/Admin.NET/Admin.NET.Core/Service/User/UserManager.cs index a408753f..e764237e 100644 --- a/Admin.NET/Admin.NET.Core/Service/User/UserManager.cs +++ b/Admin.NET/Admin.NET.Core/Service/User/UserManager.cs @@ -43,6 +43,13 @@ public class UserManager( [Newtonsoft.Json.JsonIgnore] public override long UserId => (httpContextAccessor.HttpContext?.User.FindFirst(nameof(UserId))?.Value).ToLong(); + /// + /// Token版本号 + /// + [System.Text.Json.Serialization.JsonIgnore] + [Newtonsoft.Json.JsonIgnore] + public override int TokenVersion => (httpContextAccessor.HttpContext?.User.FindFirst(nameof(UserId))?.Value).ToInt(); + /// /// 应用Id /// @@ -88,6 +95,21 @@ public class UserManager( /// public override string OrgType => Session?.OrgType; + /// + /// 职位Id + /// + public override long? PosId => Session?.PosId; + + /// + /// 职位名称 + /// + public override string PosName => Session?.PosName; + + /// + /// 职位编码 + /// + public override string PosCode => Session?.PosCode; + /// /// 组织机构级别 /// @@ -103,6 +125,41 @@ public class UserManager( /// public override string OpenId => Session?.OpenId; + /// + /// 最大数据范围权限 + /// + public override DataScopeEnum? MaxDataScope => Session?.MaxDataScope; + + /// + /// 角色Id集 + /// + public override List RoleIds => Session?.RoleIds; + + /// + /// 机构Id集 + /// + public override List OrgIds => Session?.OrgIds; + + /// + /// 职位Id集 + /// + public override List PosIds => Session?.PosIds; + + /// + /// 权限集 + /// + public override List Permissions => Session?.Permissions; + + /// + /// App权限集 + /// + public override List AppPermissions => Session?.AppPermissions; + + /// + /// 无权权限集 + /// + public override List UnauthorizedPermissions => Session?.UnauthorizedPermissions; + /// /// 扩展属性 /// @@ -119,9 +176,9 @@ public class UserManager( /// /// 设置用户Session /// - public void SetSession(UserSessionDao userSession, TimeSpan expire) + public void SetSession(UserSessionDao userSession) { - sysCacheService.Set(CacheConst.KeyUserSession + userSession.UserId, userSession, expire); + sysCacheService.Set(CacheConst.KeyUserSession + userSession.UserId, userSession); } /// @@ -140,6 +197,25 @@ public class UserManager( return sysCacheService.Get(CacheConst.KeyUserSession + userId); } + /// + /// 获取指定用户Session,如果不存在则刷新 + /// + public UserSessionDao GetSessionOrRefresh(dynamic userId = null) + { + userId ??= UserId; + var session = sysCacheService.Get(CacheConst.KeyUserSession + userId); + if (session == null) + { + if ((Nullable.GetUnderlyingType(userId.GetType()) ?? userId.GetType()) != typeof(long)) + { + if (long.TryParse(userId.ToString(), out long tempId)) userId = tempId; + else return null; + } + LazyHelper.GetService().RefreshSession(userId).GetAwaiter().GetResult(); + } + return sysCacheService.Get(CacheConst.KeyUserSession + userId); + } + /// /// 获取扩展属性 /// diff --git a/Admin.NET/Admin.NET.Core/Service/User/UserSessionDao.cs b/Admin.NET/Admin.NET.Core/Service/User/UserSessionDao.cs index b274ae76..2785bfc4 100644 --- a/Admin.NET/Admin.NET.Core/Service/User/UserSessionDao.cs +++ b/Admin.NET/Admin.NET.Core/Service/User/UserSessionDao.cs @@ -9,13 +9,20 @@ namespace Admin.NET.Core; /// /// 用户会话信息 /// -public partial class UserSessionDao +public class UserSessionDao { /// /// 用户Id /// public virtual long UserId { get; set; } + /// + /// token版本 + /// + [System.Text.Json.Serialization.JsonIgnore] + [Newtonsoft.Json.JsonIgnore] + public virtual int TokenVersion { get; set; } + /// /// 平台应用Id /// @@ -60,6 +67,11 @@ public partial class UserSessionDao [Newtonsoft.Json.JsonIgnore] public bool SysAdmin => AccountType == AccountTypeEnum.SysAdmin; + /// + /// 最大数据范围权限 + /// + public virtual DataScopeEnum? MaxDataScope { get; set; } + /// /// 组织机构Id /// @@ -85,6 +97,51 @@ public partial class UserSessionDao /// public virtual int? OrgLevel { get; set; } + /// + /// 职位Id + /// + public virtual long? PosId { get; set; } + + /// + /// 职位名称 + /// + public virtual string PosName { get; set; } + + /// + /// 职位编码 + /// + public virtual string PosCode { get; set; } + + /// + /// 角色Id集 + /// + public virtual List RoleIds { get; set; } + + /// + /// 机构Id集 + /// + public virtual List OrgIds { get; set; } + + /// + /// 职位Id集 + /// + public virtual List PosIds { get; set; } + + /// + /// 移动端权限集 + /// + public virtual List AppPermissions { get; set; } + + /// + /// 权限集 + /// + public virtual List Permissions { get; set; } + + /// + /// 无权-权限集 + /// + public virtual List UnauthorizedPermissions { get; set; } + /// /// 登录模式 /// @@ -95,11 +152,6 @@ public partial class UserSessionDao /// public virtual string OpenId { get; set; } - /// - /// token版本 - /// - public virtual long TokenVersion { get; set; } - /// /// 扩展属性 /// diff --git a/Admin.NET/Admin.NET.Core/SqlSugar/SqlSugarFilter.cs b/Admin.NET/Admin.NET.Core/SqlSugar/SqlSugarFilter.cs index 19db5f1a..f038614e 100644 --- a/Admin.NET/Admin.NET.Core/SqlSugar/SqlSugarFilter.cs +++ b/Admin.NET/Admin.NET.Core/SqlSugar/SqlSugarFilter.cs @@ -28,6 +28,10 @@ public static class SqlSugarFilter sysCacheService.Remove($"{CacheConst.KeyRoleMaxDataScope}{userId}"); // 用户权限缓存(接口集合) sysCacheService.Remove($"{CacheConst.KeyUserApi}{userId}"); + + // 清除用户session + sysCacheService.Remove($"{CacheConst.KeyUserSession}{userId}"); + // 删除用户机构(数据范围)缓存——过滤器 _cache.Remove($"db:{dbConfigId}:orgList:{userId}"); } @@ -54,6 +58,10 @@ public static class SqlSugarFilter var userId = App.User?.FindFirst(ClaimConst.UserId)?.Value; if (string.IsNullOrWhiteSpace(userId)) return; + // 获取用户session + var session = LazyHelper.GetService().GetSessionOrRefresh(userId); + if (session == null) return; + // 配置用户机构集合缓存 var cacheKey = $"db:{db.CurrentConnectionConfig.ConfigId}:orgList:{userId}"; var orgFilter = _cache.Get>(cacheKey); @@ -63,12 +71,7 @@ public static class SqlSugarFilter if (maxDataScope == (int)DataScopeEnum.All) return; // 获取用户所属机构,保证同一作用域 - var orgIds = new List(); - Scoped.Create((factory, scope) => - { - var services = scope.ServiceProvider; - orgIds = services.GetRequiredService().GetUserOrgIdList().GetAwaiter().GetResult(); - }); + var orgIds = session.OrgIds; if (orgIds == null || orgIds.Count == 0) return; // 获取业务实体数据表 @@ -109,19 +112,12 @@ public static class SqlSugarFilter var userId = App.User?.FindFirst(ClaimConst.UserId)?.Value; if (string.IsNullOrWhiteSpace(userId)) return maxDataScope; + // 获取用户session + var session = LazyHelper.GetService().GetSessionOrRefresh(userId); + if (session == null) return (int)DataScopeEnum.Self; + // 获取用户最大数据范围---仅本人数据 - maxDataScope = App.GetRequiredService().Get(CacheConst.KeyRoleMaxDataScope + userId); - // 若为0则获取用户机构组织集合建立缓存 - if (maxDataScope == 0) - { - // 获取用户所属机构,保证同一作用域 - Scoped.Create((factory, scope) => - { - var services = scope.ServiceProvider; - services.GetRequiredService().GetUserOrgIdList().GetAwaiter().GetResult(); - maxDataScope = services.GetRequiredService().Get(CacheConst.KeyRoleMaxDataScope + userId); - }); - } + maxDataScope = (int)session.MaxDataScope!; if (maxDataScope != (int)DataScopeEnum.Self) return maxDataScope; // 配置用户数据范围缓存 @@ -130,8 +126,7 @@ public static class SqlSugarFilter if (dataScopeFilter == null) { // 获取业务实体数据表 - var entityTypes = App.EffectiveTypes.Where(u => !u.IsInterface && !u.IsAbstract && u.IsClass - && u.IsSubclassOf(typeof(EntityBaseData))); + var entityTypes = App.EffectiveTypes.Where(u => !u.IsInterface && !u.IsAbstract && u.IsClass && u.IsSubclassOf(typeof(EntityBaseData))).ToList(); if (!entityTypes.Any()) return maxDataScope; dataScopeFilter = new ConcurrentDictionary(); @@ -139,8 +134,7 @@ public static class SqlSugarFilter { // 排除非当前数据库实体 var tAtt = entityType.GetCustomAttribute(); - if ((tAtt != null && db.CurrentConnectionConfig.ConfigId.ToString() != tAtt.configId.ToString())) - continue; + if ((tAtt != null && db.CurrentConnectionConfig.ConfigId.ToString() != tAtt.configId.ToString())) continue; //var lambda = DynamicExpressionParser.ParseLambda(new[] { // Expression.Parameter(entityType, "u") }, typeof(bool), $"u.{nameof(EntityBaseData.CreateUserId)}=@0", userId); @@ -172,7 +166,8 @@ public static class SqlSugarFilter { // 获取自定义实体过滤器 var entityFilterTypes = App.EffectiveTypes.Where(u => !u.IsInterface && !u.IsAbstract && u.IsClass - && u.GetInterfaces().Any(i => i.HasImplementedRawGeneric(typeof(IEntityFilter)))); + && u.GetInterfaces().Any(i => i.HasImplementedRawGeneric(typeof(IEntityFilter)))) + .ToList(); if (!entityFilterTypes.Any()) return; var tableFilterItems = new List>(); @@ -186,9 +181,9 @@ public static class SqlSugarFilter foreach (var u in entityFilters) { var tableFilterItem = (TableFilterItem)u; - var entityType = tableFilterItem.GetType().GetProperty("type", BindingFlags.Instance | BindingFlags.NonPublic).GetValue(tableFilterItem, null) as Type; + var entityType = tableFilterItem.GetType().GetProperty("type", BindingFlags.Instance | BindingFlags.NonPublic)?.GetValue(tableFilterItem, null) as Type; // 排除非当前数据库实体 - var tAtt = entityType.GetCustomAttribute(); + var tAtt = entityType?.GetCustomAttribute(); if ((tAtt != null && db.CurrentConnectionConfig.ConfigId.ToString() != tAtt.configId.ToString()) || (tAtt == null && db.CurrentConnectionConfig.ConfigId.ToString() != SqlSugarConst.MainConfigId)) continue; diff --git a/Admin.NET/Admin.NET.Web.Core/Handlers/JwtHandler.cs b/Admin.NET/Admin.NET.Web.Core/Handlers/JwtHandler.cs index 11cdef53..fba8c9be 100644 --- a/Admin.NET/Admin.NET.Web.Core/Handlers/JwtHandler.cs +++ b/Admin.NET/Admin.NET.Web.Core/Handlers/JwtHandler.cs @@ -73,7 +73,7 @@ namespace Admin.NET.Web.Core if (sysCacheService.NotExistKey($"{CacheConst.KeyUserSession}{userId}")) { var sysAuthService = serviceScope.ServiceProvider.GetRequiredService(); - await sysAuthService.RefreshToken(long.Parse(userId!)); + await sysAuthService.RefreshSession(long.Parse(userId!)); return; }