diff --git a/Yi.Framework.Net6/Build.props b/Yi.Framework.Net6/Build.props new file mode 100644 index 00000000..ee47ef8a --- /dev/null +++ b/Yi.Framework.Net6/Build.props @@ -0,0 +1,3 @@ + + + diff --git a/Yi.Framework.Net6/Version.cs b/Yi.Framework.Net6/Version.cs new file mode 100644 index 00000000..f5b81f50 --- /dev/null +++ b/Yi.Framework.Net6/Version.cs @@ -0,0 +1,90 @@ + +using System.Reflection; +using System.Runtime.InteropServices; + +[assembly: AssemblyCompany("YiFramework")] +[assembly: AssemblyFileVersion(VersionInfo.FullVersion)] +[assembly: AssemblyInformationalVersion(VersionInfo.FullVersion)] +[assembly: AssemblyVersion(VersionInfo.FullVersion)] +[assembly: ComVisible(false)] + +#pragma warning disable IDE1006 // 命名样式 +internal static class VersionInfo +{ + /// + /// 主版本: 项目进行了重大修改,导致不再向下兼容,主版本号加1,其它版本号清0; + /// + public const string Major = "1"; + + /// + /// 次版本:项目进行了重构,增加了功能,但向下兼容,子版本号加1,主版本号不变, 修正版本号清0; + /// + public const string Minor = "1"; + + /// + /// 生成号 + /// + public const string Build = "0"; + + /// + /// 修订号:项目进行了Bug修复,向下兼容,修正版本号加1,主版本号、子版本号不 变; + /// + public const string Revision = "0"; + + /// + /// 版本名称 + /// + public const string VersionName = null; + + /// + /// 版本 + /// + public const string FullVersion = Major + "." + Minor + "." + Build + "." + Revision; +#pragma warning disable CS1570 // XML 注释出现 XML 格式错误 + /// + /// 比较 a,b两个版本 + /// 当 a > b 时,返回 1 + /// 当 a = b 时,返回 0 + /// 当 a < b 时,返回 -1 + /// +#pragma warning restore CS1570 // XML 注释出现 XML 格式错误 + public static int Compare(this Version a, Version b) + + { + // 比较主版本 + if (a.Major != b.Major) + { + return a.Major > b.Major ? 1 : -1; + } + + // 比较次版本 + if (a.Minor != b.Minor) + { + return a.Minor > b.Minor ? 1 : -1; + } + + // 比较生成号 + if (a.Build < 0 || b.Build < 0) + { + return 0; + } + + if (a.Build != b.Build) + { + return a.Build > b.Build ? 1 : -1; + } + + // 比较修订号 + if (a.Revision < 0 || b.Revision < 0) + { + return 0; + } + if (a.Revision != b.Revision) + { + return a.Revision > b.Revision ? 1 : -1; + } + + return 0; + } +#pragma warning restore IDE1006 // 命名样式 +} \ No newline at end of file diff --git a/Yi.Framework.Net6/Yi.Framework.sln b/Yi.Framework.Net6/Yi.Framework.sln index 6b5befa2..a64529ea 100644 --- a/Yi.Framework.Net6/Yi.Framework.sln +++ b/Yi.Framework.Net6/Yi.Framework.sln @@ -85,7 +85,15 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Yi.RBAC.Web", "src\project\ EndProject Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Yi.Framework.ThumbnailSharp", "src\module\Yi.Framework.ThumbnailSharp\Yi.Framework.ThumbnailSharp.csproj", "{60E54034-792C-4A90-BCDF-4D5FFB45089E}" EndProject -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Yi.Framework.EventBus", "src\module\Yi.Framework.EventBus\Yi.Framework.EventBus.csproj", "{FC559052-36EC-4379-B447-298FAD6045F4}" +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Yi.Framework.EventBus", "src\module\Yi.Framework.EventBus\Yi.Framework.EventBus.csproj", "{FC559052-36EC-4379-B447-298FAD6045F4}" +EndProject +Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{12EA3BCF-8991-4010-B41E-67C476CBA690}" + ProjectSection(SolutionItems) = preProject + Build.props = Build.props + ..\readme\git提交规范.txt = ..\readme\git提交规范.txt + src\project\rbac\GlobalUsings.cs = src\project\rbac\GlobalUsings.cs + Version.cs = Version.cs + EndProjectSection EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution diff --git a/Yi.Framework.Net6/src/framework/Yi.Framework.Auth.JwtBearer/Authorization/PermissionAttribute.cs b/Yi.Framework.Net6/src/framework/Yi.Framework.Auth.JwtBearer/Authorization/PermissionAttribute.cs index 9f4fe83b..475d3180 100644 --- a/Yi.Framework.Net6/src/framework/Yi.Framework.Auth.JwtBearer/Authorization/PermissionAttribute.cs +++ b/Yi.Framework.Net6/src/framework/Yi.Framework.Auth.JwtBearer/Authorization/PermissionAttribute.cs @@ -17,30 +17,13 @@ namespace Yi.Framework.Auth.JwtBearer.Authorization public class PermissionAttribute : ActionFilterAttribute { - private string Permission { get; set; } + internal string Code { get; set; } - public PermissionAttribute(string permission) + public PermissionAttribute(string code) { - this.Permission = permission; + this.Code = code; } - /// - /// 动作鉴权 - /// - /// - /// - public override void OnActionExecuting(ActionExecutingContext context) - { - - var permissionHandler = ServiceLocatorModel.Instance.GetRequiredService(); - - var result = permissionHandler.IsPass(Permission); - - if (!result) - { - throw new AuthException(message: $"您无权限访问该接口-{ context.HttpContext.Request.Path.Value}"); - } - } } } diff --git a/Yi.Framework.Net6/src/framework/Yi.Framework.Auth.JwtBearer/Authorization/PermissionGlobalAttribute.cs b/Yi.Framework.Net6/src/framework/Yi.Framework.Auth.JwtBearer/Authorization/PermissionGlobalAttribute.cs new file mode 100644 index 00000000..06e7d17d --- /dev/null +++ b/Yi.Framework.Net6/src/framework/Yi.Framework.Auth.JwtBearer/Authorization/PermissionGlobalAttribute.cs @@ -0,0 +1,35 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Threading.Tasks; + +using Microsoft.AspNetCore.Mvc.Controllers; +using Microsoft.AspNetCore.Mvc.Filters; +using Yi.Framework.Auth.JwtBearer.Authorization; +using Yi.Framework.Core.Exceptions; + +namespace SF.AspNetCore.Auth.Authorization; +public class PermissionGlobalAttribute : ActionFilterAttribute +{ + private readonly IPermissionHandler _permissionHandler; + public PermissionGlobalAttribute(IPermissionHandler permissionHandler) + { + _permissionHandler=permissionHandler; + } + public override void OnActionExecuting(ActionExecutingContext context) + { + if (context.ActionDescriptor is not ControllerActionDescriptor controllerActionDescriptor) return; + PermissionAttribute? perAttribute = controllerActionDescriptor.MethodInfo.GetCustomAttributes(inherit: true) + .FirstOrDefault(a => a.GetType().Equals(typeof(PermissionAttribute))) as PermissionAttribute; + //空对象直接返回 + if (perAttribute is null) return; + + var result = _permissionHandler.IsPass(perAttribute.Code); + + if (!result) + { + throw new AuthException(message: $"您无权限访问该接口-{context.HttpContext.Request.Path.Value}"); + } + } +} diff --git a/Yi.Framework.Net6/src/framework/Yi.Framework.Auth.JwtBearer/YiFrameworkAuthJwtBearerModule.cs b/Yi.Framework.Net6/src/framework/Yi.Framework.Auth.JwtBearer/YiFrameworkAuthJwtBearerModule.cs index 9802d973..dbddcffe 100644 --- a/Yi.Framework.Net6/src/framework/Yi.Framework.Auth.JwtBearer/YiFrameworkAuthJwtBearerModule.cs +++ b/Yi.Framework.Net6/src/framework/Yi.Framework.Auth.JwtBearer/YiFrameworkAuthJwtBearerModule.cs @@ -1,5 +1,7 @@ using Microsoft.AspNetCore.Builder; using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Options; +using SF.AspNetCore.Auth.Authorization; using StartupModules; using System; using System.Collections.Generic; @@ -32,6 +34,10 @@ namespace Yi.Framework.Auth.JwtBearer { option.AddScheme(YiJwtAuthenticationHandler.YiJwtSchemeName, YiJwtAuthenticationHandler.YiJwtSchemeName); }); + services.AddSingleton(); + services.AddControllers(options => { + options.Filters.Add(); + }); //services.AddSingleton(); //services.AddControllers(options => { // options.Filters.Add(); diff --git a/Yi.Framework.Net6/src/project/rbac/Yi.RBAC.Application/Identity/UserService.cs b/Yi.Framework.Net6/src/project/rbac/Yi.RBAC.Application/Identity/UserService.cs index eeb4f56a..c41f34d4 100644 --- a/Yi.Framework.Net6/src/project/rbac/Yi.RBAC.Application/Identity/UserService.cs +++ b/Yi.Framework.Net6/src/project/rbac/Yi.RBAC.Application/Identity/UserService.cs @@ -11,6 +11,7 @@ using Yi.RBAC.Domain.Identity.Repositories; using SqlSugar; using Mapster; using Microsoft.AspNetCore.Mvc; +using Yi.Framework.Auth.JwtBearer.Authorization; namespace Yi.RBAC.Application.Identity { diff --git a/Yi.Framework.Net6/src/project/rbac/Yi.RBAC.Domain.Shared/Identity/Etos/LoginEventArgs.cs b/Yi.Framework.Net6/src/project/rbac/Yi.RBAC.Domain.Shared/Identity/Etos/LoginEventArgs.cs index 102d43d6..c462f2d8 100644 --- a/Yi.Framework.Net6/src/project/rbac/Yi.RBAC.Domain.Shared/Identity/Etos/LoginEventArgs.cs +++ b/Yi.Framework.Net6/src/project/rbac/Yi.RBAC.Domain.Shared/Identity/Etos/LoginEventArgs.cs @@ -10,7 +10,5 @@ namespace Yi.RBAC.Domain.Shared.Identity.Etos { public long UserId { get; set; } public string UserName { get; set; } - - public string LogMsg { get; set; } } } diff --git a/Yi.Framework.Net6/src/project/rbac/Yi.RBAC.Domain/DomainSwaggerDoc.xml b/Yi.Framework.Net6/src/project/rbac/Yi.RBAC.Domain/DomainSwaggerDoc.xml index 92e534db..d7fd7578 100644 --- a/Yi.Framework.Net6/src/project/rbac/Yi.RBAC.Domain/DomainSwaggerDoc.xml +++ b/Yi.Framework.Net6/src/project/rbac/Yi.RBAC.Domain/DomainSwaggerDoc.xml @@ -741,6 +741,20 @@ 登录信息 + + + 获取客户端信息 + + + + + + + 记录用户登陆信息 + + + + 配置表 diff --git a/Yi.Framework.Net6/src/project/rbac/Yi.RBAC.Domain/Logs/Event/LoginEventHandler .cs b/Yi.Framework.Net6/src/project/rbac/Yi.RBAC.Domain/Logs/Event/LoginEventHandler .cs index 7ff2d211..c9a69e46 100644 --- a/Yi.Framework.Net6/src/project/rbac/Yi.RBAC.Domain/Logs/Event/LoginEventHandler .cs +++ b/Yi.Framework.Net6/src/project/rbac/Yi.RBAC.Domain/Logs/Event/LoginEventHandler .cs @@ -1,4 +1,5 @@ using Cike.EventBus.EventHandlerAbstracts; +using IPTools.Core; using Microsoft.AspNetCore.Http; using System; using System.Collections.Generic; @@ -6,6 +7,8 @@ using System.Linq; using System.Net.Http; using System.Text; using System.Threading.Tasks; +using UAParser; +using Yi.Framework.AspNetCore.Extensions; using Yi.Framework.Ddd.Repositories; using Yi.RBAC.Domain.Logs.Entities; using Yi.RBAC.Domain.Shared.Identity.Etos; @@ -23,14 +26,56 @@ namespace Yi.RBAC.Domain.Logs.Event } public Task HandlerAsync(LoginEventArgs eventData) { - var loginLogEntity = new LoginLogEntity(); + var loginLogEntity = GetLoginLogInfo(_httpContext); loginLogEntity.Id = SnowflakeHelper.NextId; - loginLogEntity.LogMsg = eventData.LogMsg; + loginLogEntity.LogMsg = eventData.UserName + "登录系统"; loginLogEntity.LoginUser = eventData.UserName; + loginLogEntity.LoginIp = _httpContext.GetClientIp(); _loginLogRepository.InsertAsync(loginLogEntity); - Console.WriteLine(eventData.UserName + "登录系统"); return Task.CompletedTask; } + + /// + /// 获取客户端信息 + /// + /// + /// + private static ClientInfo GetClientInfo(HttpContext context) + { + var str = context.GetUserAgent(); + var uaParser = Parser.GetDefault(); + ClientInfo c = uaParser.Parse(str); + return c; + } + + /// + /// 记录用户登陆信息 + /// + /// + /// + private static LoginLogEntity GetLoginLogInfo(HttpContext context) + { + var ipAddr = context.GetClientIp(); + IpInfo location; + if (ipAddr == "127.0.0.1") + { + location = new IpInfo() { Province = "本地", City = "本机" }; + } + else + { + location = IpTool.Search(ipAddr); + } + ClientInfo clientInfo = GetClientInfo(context); + LoginLogEntity entity = new() + { + Browser = clientInfo.Device.Family, + Os = clientInfo.OS.ToString(), + LoginIp = ipAddr, + LoginLocation = location.Province + "-" + location.City + }; + + return entity; + } } } diff --git a/Yi.Framework.Net6/src/project/rbac/Yi.RBAC.Domain/Yi.RBAC.Domain.csproj b/Yi.Framework.Net6/src/project/rbac/Yi.RBAC.Domain/Yi.RBAC.Domain.csproj index cfb38688..d8fd344f 100644 --- a/Yi.Framework.Net6/src/project/rbac/Yi.RBAC.Domain/Yi.RBAC.Domain.csproj +++ b/Yi.Framework.Net6/src/project/rbac/Yi.RBAC.Domain/Yi.RBAC.Domain.csproj @@ -12,6 +12,8 @@ + + diff --git a/Yi.Framework.Net6/src/project/rbac/Yi.RBAC.Web/Yi.RBAC.Web.csproj b/Yi.Framework.Net6/src/project/rbac/Yi.RBAC.Web/Yi.RBAC.Web.csproj index 8c910776..a40b060c 100644 --- a/Yi.Framework.Net6/src/project/rbac/Yi.RBAC.Web/Yi.RBAC.Web.csproj +++ b/Yi.Framework.Net6/src/project/rbac/Yi.RBAC.Web/Yi.RBAC.Web.csproj @@ -16,6 +16,9 @@ + + Always + Always diff --git a/Yi.Framework.Net6/src/project/rbac/Yi.RBAC.Web/ip2region.db b/Yi.Framework.Net6/src/project/rbac/Yi.RBAC.Web/ip2region.db new file mode 100644 index 00000000..0fc60e6c Binary files /dev/null and b/Yi.Framework.Net6/src/project/rbac/Yi.RBAC.Web/ip2region.db differ