17 changed files with 251 additions and 112 deletions
@ -0,0 +1,3 @@ |
|||||
|
<Weavers xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="FodyWeavers.xsd"> |
||||
|
<ConfigureAwait /> |
||||
|
</Weavers> |
||||
@ -0,0 +1,30 @@ |
|||||
|
<?xml version="1.0" encoding="utf-8"?> |
||||
|
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"> |
||||
|
<!-- This file was generated by Fody. Manual changes to this file will be lost when your project is rebuilt. --> |
||||
|
<xs:element name="Weavers"> |
||||
|
<xs:complexType> |
||||
|
<xs:all> |
||||
|
<xs:element name="ConfigureAwait" minOccurs="0" maxOccurs="1"> |
||||
|
<xs:complexType> |
||||
|
<xs:attribute name="ContinueOnCapturedContext" type="xs:boolean" /> |
||||
|
</xs:complexType> |
||||
|
</xs:element> |
||||
|
</xs:all> |
||||
|
<xs:attribute name="VerifyAssembly" type="xs:boolean"> |
||||
|
<xs:annotation> |
||||
|
<xs:documentation>'true' to run assembly verification (PEVerify) on the target assembly after all weavers have been executed.</xs:documentation> |
||||
|
</xs:annotation> |
||||
|
</xs:attribute> |
||||
|
<xs:attribute name="VerifyIgnoreCodes" type="xs:string"> |
||||
|
<xs:annotation> |
||||
|
<xs:documentation>A comma-separated list of error codes that can be safely ignored in assembly verification.</xs:documentation> |
||||
|
</xs:annotation> |
||||
|
</xs:attribute> |
||||
|
<xs:attribute name="GenerateXsd" type="xs:boolean"> |
||||
|
<xs:annotation> |
||||
|
<xs:documentation>'false' to turn off automatic generation of the XML Schema file.</xs:documentation> |
||||
|
</xs:annotation> |
||||
|
</xs:attribute> |
||||
|
</xs:complexType> |
||||
|
</xs:element> |
||||
|
</xs:schema> |
||||
@ -0,0 +1,25 @@ |
|||||
|
<Project Sdk="Microsoft.NET.Sdk"> |
||||
|
|
||||
|
<Import Project="..\..\..\..\configureawait.props" /> |
||||
|
<Import Project="..\..\..\..\common.props" /> |
||||
|
|
||||
|
<PropertyGroup> |
||||
|
<TargetFrameworks>netstandard2.0;netstandard2.1;net8.0</TargetFrameworks> |
||||
|
<Nullable>enable</Nullable> |
||||
|
<WarningsAsErrors>Nullable</WarningsAsErrors> |
||||
|
<AssemblyName>LINGYUN.Abp.AuditLogging.IP2Region</AssemblyName> |
||||
|
<PackageId>LINGYUN.Abp.AuditLogging.IP2Region</PackageId> |
||||
|
<GenerateAssemblyConfigurationAttribute>false</GenerateAssemblyConfigurationAttribute> |
||||
|
<GenerateAssemblyCompanyAttribute>false</GenerateAssemblyCompanyAttribute> |
||||
|
<GenerateAssemblyProductAttribute>false</GenerateAssemblyProductAttribute> |
||||
|
<RootNamespace /> |
||||
|
</PropertyGroup><PropertyGroup> |
||||
|
<TargetFramework>netstandard2.0</TargetFramework> |
||||
|
</PropertyGroup> |
||||
|
|
||||
|
<ItemGroup> |
||||
|
<ProjectReference Include="..\..\common\LINGYUN.Abp.IP2Region\LINGYUN.Abp.IP2Region.csproj" /> |
||||
|
<ProjectReference Include="..\LINGYUN.Abp.AuditLogging\LINGYUN.Abp.AuditLogging.csproj" /> |
||||
|
</ItemGroup> |
||||
|
|
||||
|
</Project> |
||||
@ -0,0 +1,26 @@ |
|||||
|
using LINGYUN.Abp.IP2Region; |
||||
|
using Microsoft.Extensions.DependencyInjection; |
||||
|
using Microsoft.Extensions.DependencyInjection.Extensions; |
||||
|
using Volo.Abp.Auditing; |
||||
|
using Volo.Abp.Modularity; |
||||
|
using Volo.Abp.SecurityLog; |
||||
|
|
||||
|
namespace LINGYUN.Abp.AuditLogging.IP2Region; |
||||
|
|
||||
|
[DependsOn( |
||||
|
typeof(AbpIP2RegionModule), |
||||
|
typeof(AbpAuditLoggingModule))] |
||||
|
public class AbpAuditLoggingIP2RegionModule : AbpModule |
||||
|
{ |
||||
|
public override void PostConfigureServices(ServiceConfigurationContext context) |
||||
|
{ |
||||
|
var configuration = context.Services.GetConfiguration(); |
||||
|
|
||||
|
Configure<AbpAuditLoggingIP2RegionOptions>(configuration.GetSection("AuditLogging:IP2Region")); |
||||
|
|
||||
|
context.Services.Replace( |
||||
|
ServiceDescriptor.Transient<IAuditingStore, IP2RegionAuditingStore>()); |
||||
|
context.Services.Replace( |
||||
|
ServiceDescriptor.Transient<ISecurityLogStore, IP2RegionSecurityLogStore>()); |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,5 @@ |
|||||
|
namespace LINGYUN.Abp.AuditLogging.IP2Region; |
||||
|
public class AbpAuditLoggingIP2RegionOptions |
||||
|
{ |
||||
|
public bool IsEnabled { get; set; } |
||||
|
} |
||||
@ -0,0 +1,34 @@ |
|||||
|
using LINGYUN.Abp.IP2Region; |
||||
|
using Microsoft.Extensions.Options; |
||||
|
using System; |
||||
|
using System.Threading.Tasks; |
||||
|
using Volo.Abp.Auditing; |
||||
|
|
||||
|
namespace LINGYUN.Abp.AuditLogging.IP2Region; |
||||
|
public class IP2RegionAuditingStore : AuditingStore |
||||
|
{ |
||||
|
private readonly AbpAuditLoggingIP2RegionOptions _options; |
||||
|
private readonly IIpLocationInfoProvider _ipLocationInfoProvider; |
||||
|
public IP2RegionAuditingStore( |
||||
|
IOptionsMonitor<AbpAuditLoggingIP2RegionOptions> options, |
||||
|
IIpLocationInfoProvider ipLocationInfoProvider, |
||||
|
IAuditLogManager manager) |
||||
|
: base(manager) |
||||
|
{ |
||||
|
_options = options.CurrentValue; |
||||
|
_ipLocationInfoProvider = ipLocationInfoProvider; |
||||
|
} |
||||
|
|
||||
|
public async override Task SaveAsync(AuditLogInfo auditInfo) |
||||
|
{ |
||||
|
if (_options.IsEnabled && !auditInfo.ClientIpAddress.IsNullOrWhiteSpace()) |
||||
|
{ |
||||
|
var locationInfo = await _ipLocationInfoProvider.GetLocationInfoAsync(auditInfo.ClientIpAddress); |
||||
|
if (locationInfo?.Remarks?.IsNullOrWhiteSpace() == false) |
||||
|
{ |
||||
|
auditInfo.ExtraProperties.Add("Location", $"{locationInfo.Remarks}"); |
||||
|
} |
||||
|
} |
||||
|
await base.SaveAsync(auditInfo); |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,36 @@ |
|||||
|
using LINGYUN.Abp.IP2Region; |
||||
|
using Microsoft.Extensions.Options; |
||||
|
using System; |
||||
|
using System.Threading.Tasks; |
||||
|
using Volo.Abp.SecurityLog; |
||||
|
|
||||
|
namespace LINGYUN.Abp.AuditLogging.IP2Region; |
||||
|
|
||||
|
public class IP2RegionSecurityLogStore : SecurityLogStore |
||||
|
{ |
||||
|
private readonly AbpAuditLoggingIP2RegionOptions _options; |
||||
|
private readonly IIpLocationInfoProvider _ipLocationInfoProvider; |
||||
|
public IP2RegionSecurityLogStore( |
||||
|
IOptionsMonitor<AbpAuditLoggingIP2RegionOptions> options, |
||||
|
IIpLocationInfoProvider ipLocationInfoProvider, |
||||
|
ISecurityLogManager manager) |
||||
|
: base(manager) |
||||
|
{ |
||||
|
_options = options.CurrentValue; |
||||
|
_ipLocationInfoProvider = ipLocationInfoProvider; |
||||
|
} |
||||
|
|
||||
|
public async override Task SaveAsync(SecurityLogInfo securityLogInfo) |
||||
|
{ |
||||
|
if (_options.IsEnabled && !securityLogInfo.ClientIpAddress.IsNullOrWhiteSpace()) |
||||
|
{ |
||||
|
var locationInfo = await _ipLocationInfoProvider.GetLocationInfoAsync(securityLogInfo.ClientIpAddress); |
||||
|
if (locationInfo?.Remarks?.IsNullOrWhiteSpace() == false) |
||||
|
{ |
||||
|
securityLogInfo.ExtraProperties.Add("Location", $"{locationInfo.Remarks}"); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
await base.SaveAsync(securityLogInfo); |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,68 @@ |
|||||
|
using IP2Region.Net.Abstractions; |
||||
|
using System; |
||||
|
using System.Threading.Tasks; |
||||
|
|
||||
|
namespace LINGYUN.Abp.IP2Region; |
||||
|
|
||||
|
public class IP2RegionLocationInfoProvider : IIpLocationInfoProvider |
||||
|
{ |
||||
|
protected static readonly LocationInfo? _nullCache = null; |
||||
|
|
||||
|
protected ISearcher Searcher { get; } |
||||
|
public IP2RegionLocationInfoProvider(ISearcher searcher) |
||||
|
{ |
||||
|
Searcher = searcher; |
||||
|
} |
||||
|
|
||||
|
public virtual Task<LocationInfo?> GetLocationInfoAsync(string ipAddress) |
||||
|
{ |
||||
|
var region = Searcher.Search(ipAddress); |
||||
|
if (string.IsNullOrWhiteSpace(region)) |
||||
|
{ |
||||
|
return Task.FromResult(_nullCache); |
||||
|
} |
||||
|
|
||||
|
var regions = region!.Split('|'); |
||||
|
// | 0 | 1 | 2 |3| 4 | 5 | 6 |
|
||||
|
// 39.128.0.0|39.128.31.255|中国|0|云南省|昆明市|移动
|
||||
|
// regions:
|
||||
|
// 中国 0 云南省 昆明市 移动
|
||||
|
var locationInfo = new LocationInfo |
||||
|
{ |
||||
|
Country = regions.Length >= 1 && !string.Equals(regions[0], "0") ? regions[0] : null, |
||||
|
Province = regions.Length >= 3 && !string.Equals(regions[2], "0") ? regions[2] : null, |
||||
|
City = regions.Length >= 4 && !string.Equals(regions[3], "0") ? regions[3] : null, |
||||
|
}; |
||||
|
|
||||
|
// 36.133.108.0|36.133.119.255|中国|0|重庆|重庆市|移动
|
||||
|
if (!locationInfo.Province.IsNullOrWhiteSpace() && !locationInfo.City.IsNullOrWhiteSpace()) |
||||
|
{ |
||||
|
if (locationInfo.Province.Length < locationInfo.City.Length && |
||||
|
locationInfo.City.StartsWith(locationInfo.Province, StringComparison.InvariantCultureIgnoreCase)) |
||||
|
{ |
||||
|
// 重庆市
|
||||
|
locationInfo.Remarks = $"{locationInfo.City}"; |
||||
|
} |
||||
|
// 111.26.31.0|111.26.31.127|中国|0|吉林省|吉林市|移动
|
||||
|
else |
||||
|
{ |
||||
|
// 吉林省吉林市
|
||||
|
locationInfo.Remarks = $"{locationInfo.Province}{locationInfo.City}"; |
||||
|
} |
||||
|
} |
||||
|
// 220.246.0.0|220.246.255.255|中国|0|香港|0|电讯盈科
|
||||
|
else if (!locationInfo.Country.IsNullOrWhiteSpace() && !locationInfo.Province.IsNullOrWhiteSpace()) |
||||
|
{ |
||||
|
// 中国香港
|
||||
|
locationInfo.Remarks = $"{locationInfo.Country}{locationInfo.Province}"; |
||||
|
} |
||||
|
// 220.247.4.0|220.247.31.255|日本|0|0|0|0
|
||||
|
else |
||||
|
{ |
||||
|
// 日本
|
||||
|
locationInfo.Remarks = $"{locationInfo.Country}"; |
||||
|
} |
||||
|
|
||||
|
return Task.FromResult<LocationInfo?>(locationInfo); |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,8 @@ |
|||||
|
namespace LINGYUN.Abp.IP2Region; |
||||
|
public class LocationInfo |
||||
|
{ |
||||
|
public string? Country { get; set; } |
||||
|
public string? Province { get; set; } |
||||
|
public string? City { get; set; } |
||||
|
public string? Remarks { get; set; } |
||||
|
} |
||||
@ -1,48 +1,13 @@ |
|||||
using System; |
namespace LINGYUN.Abp.Identity.Session.AspNetCore; |
||||
using System.Collections.Generic; |
|
||||
|
|
||||
namespace LINGYUN.Abp.Identity.Session.AspNetCore; |
|
||||
public class AbpIdentitySessionAspNetCoreOptions |
public class AbpIdentitySessionAspNetCoreOptions |
||||
{ |
{ |
||||
/// <summary>
|
/// <summary>
|
||||
/// 是否解析IP地理信息
|
/// 是否解析IP地理信息
|
||||
/// </summary>
|
/// </summary>
|
||||
public bool IsParseIpLocation { get; set; } |
public bool IsParseIpLocation { get; set; } |
||||
/// <summary>
|
|
||||
/// 不做处理的省份
|
|
||||
/// </summary>
|
|
||||
public IList<string> IgnoreProvinces { get; set; } |
|
||||
/// <summary>
|
|
||||
/// 地理信息解析
|
|
||||
/// </summary>
|
|
||||
public Func<LocationInfo, string> LocationParser { get; set; } |
|
||||
|
|
||||
public AbpIdentitySessionAspNetCoreOptions() |
public AbpIdentitySessionAspNetCoreOptions() |
||||
{ |
{ |
||||
IsParseIpLocation = false; |
IsParseIpLocation = false; |
||||
IgnoreProvinces = new List<string> |
|
||||
{ |
|
||||
// 中国直辖市不显示省份数据
|
|
||||
"北京", "上海", "天津", "重庆" |
|
||||
}; |
|
||||
LocationParser = (locationInfo) => |
|
||||
{ |
|
||||
var location = ""; |
|
||||
|
|
||||
if (!locationInfo.Province.IsNullOrWhiteSpace() && |
|
||||
!IgnoreProvinces.Contains(locationInfo.Province)) |
|
||||
{ |
|
||||
location += locationInfo.Province + " "; |
|
||||
} |
|
||||
if (!locationInfo.City.IsNullOrWhiteSpace()) |
|
||||
{ |
|
||||
location += locationInfo.City; |
|
||||
} |
|
||||
if (location.IsNullOrWhiteSpace() && !locationInfo.Country.IsNullOrWhiteSpace()) |
|
||||
{ |
|
||||
location = locationInfo.Country; |
|
||||
} |
|
||||
return location; |
|
||||
}; |
|
||||
} |
} |
||||
} |
} |
||||
|
|||||
@ -1,36 +0,0 @@ |
|||||
using IP2Region.Net.Abstractions; |
|
||||
using System; |
|
||||
using System.Threading.Tasks; |
|
||||
|
|
||||
namespace LINGYUN.Abp.Identity.Session.AspNetCore; |
|
||||
|
|
||||
public class IP2RegionLocationInfoProvider : IIpLocationInfoProvider |
|
||||
{ |
|
||||
protected static readonly LocationInfo _nullCache = null; |
|
||||
|
|
||||
protected ISearcher Searcher { get; } |
|
||||
public IP2RegionLocationInfoProvider(ISearcher searcher) |
|
||||
{ |
|
||||
Searcher = searcher; |
|
||||
} |
|
||||
|
|
||||
public virtual Task<LocationInfo> GetLocationInfoAsync(string ipAddress) |
|
||||
{ |
|
||||
var region = Searcher.Search(ipAddress); |
|
||||
if (region.IsNullOrWhiteSpace()) |
|
||||
{ |
|
||||
return Task.FromResult(_nullCache); |
|
||||
} |
|
||||
|
|
||||
var regions = region.Split('|'); |
|
||||
// | 0 | 1 | 2 |3| 4 | 5 | 6 |
|
|
||||
// 39.128.0.0|39.128.31.255|中国|0|云南省|昆明市|移动
|
|
||||
var locationInfo = new LocationInfo |
|
||||
{ |
|
||||
Country = regions.Length >= 3 && !string.Equals(regions[2], "0") ? regions[2] : null, |
|
||||
Province = regions.Length >= 5 && !string.Equals(regions[4], "0") ? regions[4] : null, |
|
||||
City = regions.Length >= 6 && !string.Equals(regions[5], "0") ? regions[5] : null, |
|
||||
}; |
|
||||
return Task.FromResult(locationInfo); |
|
||||
} |
|
||||
} |
|
||||
@ -1,7 +0,0 @@ |
|||||
namespace LINGYUN.Abp.Identity.Session; |
|
||||
public class LocationInfo |
|
||||
{ |
|
||||
public string Country { get; set; } |
|
||||
public string Province { get; set; } |
|
||||
public string City { get; set; } |
|
||||
} |
|
||||
@ -1,15 +0,0 @@ |
|||||
using Microsoft.Extensions.DependencyInjection; |
|
||||
using System.Threading.Tasks; |
|
||||
using Volo.Abp.DependencyInjection; |
|
||||
|
|
||||
namespace LINGYUN.Abp.Identity.Session; |
|
||||
|
|
||||
[Dependency(ServiceLifetime.Singleton, TryRegister = true)] |
|
||||
public class NoneIpLocationInfoProvider : IIpLocationInfoProvider |
|
||||
{ |
|
||||
protected static readonly LocationInfo _nullCache = null; |
|
||||
public Task<LocationInfo> GetLocationInfoAsync(string ipAddress) |
|
||||
{ |
|
||||
return Task.FromResult(_nullCache); |
|
||||
} |
|
||||
} |
|
||||
Loading…
Reference in new issue