diff --git a/aspnet-core/Directory.Build.targets b/aspnet-core/Directory.Build.targets index a6aa15d3..322bc41d 100644 --- a/aspnet-core/Directory.Build.targets +++ b/aspnet-core/Directory.Build.targets @@ -118,5 +118,7 @@ + + \ No newline at end of file diff --git a/aspnet-core/frameworks/src/Lion.AbpPro.AspNetCore/Lion/AbpPro/AspNetCore/AbpProAspNetCoreModule.cs b/aspnet-core/frameworks/src/Lion.AbpPro.AspNetCore/Lion/AbpPro/AspNetCore/AbpProAspNetCoreModule.cs index 563574ba..90140dca 100644 --- a/aspnet-core/frameworks/src/Lion.AbpPro.AspNetCore/Lion/AbpPro/AspNetCore/AbpProAspNetCoreModule.cs +++ b/aspnet-core/frameworks/src/Lion.AbpPro.AspNetCore/Lion/AbpPro/AspNetCore/AbpProAspNetCoreModule.cs @@ -1,6 +1,8 @@ using Lion.AbpPro.AspNetCore.Options; +using Microsoft.Extensions.DependencyInjection.Extensions; using Volo.Abp.AspNetCore.MultiTenancy; using Volo.Abp.AspNetCore.Mvc.UI.Theme.Basic; +using Volo.Abp.AspNetCore.WebClientInfo; namespace Lion.AbpPro.AspNetCore; @@ -22,5 +24,11 @@ public class AbpProAspNetCoreModule : AbpModule context.Services.Configure(context.Configuration.GetSection(AbpProAspNetCoreConsts.Jwt)); context.Services.Configure(context.Configuration.GetSection(AbpProAspNetCoreConsts.Cookie)); context.Services.Configure(context.Configuration.GetSection(AbpProAspNetCoreConsts.AntiForgery)); + + // 替换默认的WebClientInfoProvider为支持代理的实现 + context.Services.Replace(new ServiceDescriptor( + typeof(IWebClientInfoProvider), + typeof(RealIpHttpContextWebClientInfoProvider), + ServiceLifetime.Transient)); } } \ No newline at end of file diff --git a/aspnet-core/frameworks/src/Lion.AbpPro.AspNetCore/Lion/AbpPro/AspNetCore/RealIpHttpContextWebClientInfoProvider.cs b/aspnet-core/frameworks/src/Lion.AbpPro.AspNetCore/Lion/AbpPro/AspNetCore/RealIpHttpContextWebClientInfoProvider.cs new file mode 100644 index 00000000..572caedb --- /dev/null +++ b/aspnet-core/frameworks/src/Lion.AbpPro.AspNetCore/Lion/AbpPro/AspNetCore/RealIpHttpContextWebClientInfoProvider.cs @@ -0,0 +1,56 @@ +using JetBrains.Annotations; +using MyCSharp.HttpUserAgentParser.Providers; +using Volo.Abp.AspNetCore.WebClientInfo; + +namespace Lion.AbpPro.AspNetCore; + +/// +/// 真实IP地址提供程序,支持代理服务器场景 +/// +public class RealIpHttpContextWebClientInfoProvider : HttpContextWebClientInfoProvider +{ + private const string XForwardedForHeader = "X-Forwarded-For"; + + + public RealIpHttpContextWebClientInfoProvider( + ILogger logger, + IHttpContextAccessor httpContextAccessor, + IHttpUserAgentParserProvider httpUserAgentParser) + : base(logger, httpContextAccessor, httpUserAgentParser) + { + } + + /// + /// 获取客户端IP地址,优先从X-Forwarded-For头部获取 + /// + /// 客户端IP地址 + protected override string GetClientIpAddress() + { + try + { + var httpContext = HttpContextAccessor.HttpContext; + if (httpContext == null) + { + return null; + } + + var headers = httpContext.Request?.Headers; + if (headers != null && headers.ContainsKey(XForwardedForHeader)) + { + // 从X-Forwarded-For获取真实客户端IP + var forwardedIp = headers[XForwardedForHeader].FirstOrDefault(); + if (!string.IsNullOrEmpty(forwardedIp)) + { + httpContext.Connection.RemoteIpAddress = IPAddress.Parse(forwardedIp); + } + } + + return httpContext.Connection?.RemoteIpAddress?.ToString(); + } + catch (Exception ex) + { + Logger.LogWarning(ex, "获取客户端IP地址时发生异常"); + return null; + } + } +} \ No newline at end of file diff --git a/aspnet-core/modules/BasicManagement/src/Lion.AbpPro.BasicManagement.Domain/AuditLogs/AbpProAuditLogInfoToAuditLogConverter.cs b/aspnet-core/modules/BasicManagement/src/Lion.AbpPro.BasicManagement.Domain/AuditLogs/AbpProAuditLogInfoToAuditLogConverter.cs new file mode 100644 index 00000000..12f491b6 --- /dev/null +++ b/aspnet-core/modules/BasicManagement/src/Lion.AbpPro.BasicManagement.Domain/AuditLogs/AbpProAuditLogInfoToAuditLogConverter.cs @@ -0,0 +1,84 @@ +using IPTools.Core; +using Microsoft.Extensions.Options; +using UAParser; +using Volo.Abp.AspNetCore.ExceptionHandling; +using Volo.Abp.DependencyInjection; +using Volo.Abp.Guids; +using Volo.Abp.Json; + +namespace Lion.AbpPro.BasicManagement.AuditLogs; + +[Dependency(ReplaceServices = true)] +[ExposeServices(typeof(IAuditLogInfoToAuditLogConverter))] +public class AbpProAuditLogInfoToAuditLogConverter : AuditLogInfoToAuditLogConverter +{ + public AbpProAuditLogInfoToAuditLogConverter( + IGuidGenerator guidGenerator, + IExceptionToErrorInfoConverter exceptionToErrorInfoConverter, + IJsonSerializer jsonSerializer, + IOptions exceptionHandlingOptions, + AuditLogEntityTypeFullNameConverter auditLogEntityTypeFullNameConverter) + : base( + guidGenerator, + exceptionToErrorInfoConverter, + jsonSerializer, + exceptionHandlingOptions, + auditLogEntityTypeFullNameConverter) + { + } + + public override Task ConvertAsync(AuditLogInfo auditLogInfo) + { + auditLogInfo.ClientIpAddress = GetClientIpAddress(auditLogInfo); + auditLogInfo.BrowserInfo = GetBrowserInfo(auditLogInfo); + return base.ConvertAsync(auditLogInfo); + } + + /// + /// 获取客户端IP地址 + /// + /// 审计日志信息 + /// IP地址 + protected virtual string GetClientIpAddress(AuditLogInfo auditLogInfo) + { + var ipAddr = auditLogInfo.ClientIpAddress; + IpInfo location; + if (auditLogInfo.ClientIpAddress == "127.0.0.1" || auditLogInfo.ClientIpAddress?.ToLower() == "localhost") + { + return "本地-本机"; + } + + try + { + location = IpTool.Search(ipAddr); + } + catch + { + location = new IpInfo() { Province = ipAddr, City = "未知地区" }; + } + + return location.Province + "-" + location.City; + } + + /// + /// 获取浏览器信息 + /// + /// 审计日志信息 + /// 浏览器信息 + protected virtual string GetBrowserInfo(AuditLogInfo auditLogInfo) + { + try + { + if (auditLogInfo.BrowserInfo.IsNotNullOrWhiteSpace()) + { + var uaParser = Parser.GetDefault(); + return uaParser.Parse(auditLogInfo.BrowserInfo).UA.ToString(); + } + } + catch + { + return "Other"; + } + return auditLogInfo.BrowserInfo; + } +} \ No newline at end of file diff --git a/aspnet-core/modules/BasicManagement/src/Lion.AbpPro.BasicManagement.Domain/Lion.AbpPro.BasicManagement.Domain.csproj b/aspnet-core/modules/BasicManagement/src/Lion.AbpPro.BasicManagement.Domain/Lion.AbpPro.BasicManagement.Domain.csproj index 48d21cdc..cb954d02 100644 --- a/aspnet-core/modules/BasicManagement/src/Lion.AbpPro.BasicManagement.Domain/Lion.AbpPro.BasicManagement.Domain.csproj +++ b/aspnet-core/modules/BasicManagement/src/Lion.AbpPro.BasicManagement.Domain/Lion.AbpPro.BasicManagement.Domain.csproj @@ -14,6 +14,8 @@ + + diff --git a/aspnet-core/services/host/Lion.AbpPro.HttpApi.Host/Lion.AbpPro.HttpApi.Host.csproj b/aspnet-core/services/host/Lion.AbpPro.HttpApi.Host/Lion.AbpPro.HttpApi.Host.csproj index 6e45f72f..82e62545 100644 --- a/aspnet-core/services/host/Lion.AbpPro.HttpApi.Host/Lion.AbpPro.HttpApi.Host.csproj +++ b/aspnet-core/services/host/Lion.AbpPro.HttpApi.Host/Lion.AbpPro.HttpApi.Host.csproj @@ -37,6 +37,9 @@ + + Always + diff --git a/aspnet-core/services/host/Lion.AbpPro.HttpApi.Host/Program.cs b/aspnet-core/services/host/Lion.AbpPro.HttpApi.Host/Program.cs index 18af11e0..a9014a9a 100644 --- a/aspnet-core/services/host/Lion.AbpPro.HttpApi.Host/Program.cs +++ b/aspnet-core/services/host/Lion.AbpPro.HttpApi.Host/Program.cs @@ -11,7 +11,7 @@ public class Program try { - Log.Information("Lion.AbpPro.HttpApi.Host."); + Log.Information("Lion.AbpPro启动成功"); var builder = WebApplication.CreateBuilder(args); builder.Host .AddAppSettingsSecretsJson() @@ -30,12 +30,11 @@ public class Program } catch (Exception ex) { + Log.Fatal(ex, "Lion.AbpPro启动失败"); if (ex is HostAbortedException) { throw; } - - Log.Fatal(ex, "Host terminated unexpectedly!"); return 1; } finally diff --git a/aspnet-core/services/host/Lion.AbpPro.HttpApi.Host/appsettings.Development.json b/aspnet-core/services/host/Lion.AbpPro.HttpApi.Host/appsettings.Development.json index e255721d..23d292fa 100644 --- a/aspnet-core/services/host/Lion.AbpPro.HttpApi.Host/appsettings.Development.json +++ b/aspnet-core/services/host/Lion.AbpPro.HttpApi.Host/appsettings.Development.json @@ -1,6 +1,6 @@ { "ConnectionStrings": { - "Default": "User ID=postgres;Password=1q2w3E*;Host=localhost;Port=5432;Database=LionAbpProDb;" + "Default": "User ID=abpprovben2;Password=rjrwHpkA3JKyS6S8;Host=139.155.114.244;Port=5432;Database=abpprovben2;" }, "Hangfire": { "Redis": { diff --git a/aspnet-core/services/host/Lion.AbpPro.HttpApi.Host/ip2region.db b/aspnet-core/services/host/Lion.AbpPro.HttpApi.Host/ip2region.db new file mode 100644 index 00000000..0fc60e6c Binary files /dev/null and b/aspnet-core/services/host/Lion.AbpPro.HttpApi.Host/ip2region.db differ diff --git a/templates/pro-nuget/service/host/MyCompanyName.MyProjectName.HttpApi.Host/MyCompanyName.MyProjectName.HttpApi.Host.csproj b/templates/pro-nuget/service/host/MyCompanyName.MyProjectName.HttpApi.Host/MyCompanyName.MyProjectName.HttpApi.Host.csproj index 3cef0b87..22a53fc6 100644 --- a/templates/pro-nuget/service/host/MyCompanyName.MyProjectName.HttpApi.Host/MyCompanyName.MyProjectName.HttpApi.Host.csproj +++ b/templates/pro-nuget/service/host/MyCompanyName.MyProjectName.HttpApi.Host/MyCompanyName.MyProjectName.HttpApi.Host.csproj @@ -38,6 +38,9 @@ + + Always + diff --git a/templates/pro-nuget/service/host/MyCompanyName.MyProjectName.HttpApi.Host/ip2region.db b/templates/pro-nuget/service/host/MyCompanyName.MyProjectName.HttpApi.Host/ip2region.db new file mode 100644 index 00000000..0fc60e6c Binary files /dev/null and b/templates/pro-nuget/service/host/MyCompanyName.MyProjectName.HttpApi.Host/ip2region.db differ