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)