33 changed files with 469 additions and 183 deletions
@ -1,26 +1,26 @@ |
|||||
using LINGYUN.Abp.IP2Region; |
using LINGYUN.Abp.IP.Location; |
||||
using Microsoft.Extensions.DependencyInjection; |
using Microsoft.Extensions.DependencyInjection; |
||||
using Microsoft.Extensions.DependencyInjection.Extensions; |
using Microsoft.Extensions.DependencyInjection.Extensions; |
||||
using Volo.Abp.Auditing; |
using Volo.Abp.Auditing; |
||||
using Volo.Abp.Modularity; |
using Volo.Abp.Modularity; |
||||
using Volo.Abp.SecurityLog; |
using Volo.Abp.SecurityLog; |
||||
|
|
||||
namespace LINGYUN.Abp.AuditLogging.IP2Region; |
namespace LINGYUN.Abp.AuditLogging.IP.Location; |
||||
|
|
||||
[DependsOn( |
[DependsOn( |
||||
typeof(AbpIP2RegionModule), |
typeof(AbpIPLocationModule), |
||||
typeof(AbpAuditLoggingModule))] |
typeof(AbpAuditLoggingModule))] |
||||
public class AbpAuditLoggingIP2RegionModule : AbpModule |
public class AbpAuditLoggingIPLocationModule : AbpModule |
||||
{ |
{ |
||||
public override void PostConfigureServices(ServiceConfigurationContext context) |
public override void PostConfigureServices(ServiceConfigurationContext context) |
||||
{ |
{ |
||||
var configuration = context.Services.GetConfiguration(); |
var configuration = context.Services.GetConfiguration(); |
||||
|
|
||||
Configure<AbpAuditLoggingIP2RegionOptions>(configuration.GetSection("AuditLogging:IP2Region")); |
Configure<AbpAuditLoggingIPLocationOptions>(configuration.GetSection("AuditLogging:IPLocation")); |
||||
|
|
||||
context.Services.Replace( |
context.Services.Replace( |
||||
ServiceDescriptor.Transient<IAuditingStore, IP2RegionAuditingStore>()); |
ServiceDescriptor.Transient<IAuditingStore, IPLocationAuditingStore>()); |
||||
context.Services.Replace( |
context.Services.Replace( |
||||
ServiceDescriptor.Transient<ISecurityLogStore, IP2RegionSecurityLogStore>()); |
ServiceDescriptor.Transient<ISecurityLogStore, IPLocationSecurityLogStore>()); |
||||
} |
} |
||||
} |
} |
||||
@ -0,0 +1,5 @@ |
|||||
|
namespace LINGYUN.Abp.AuditLogging.IP.Location; |
||||
|
public class AbpAuditLoggingIPLocationOptions |
||||
|
{ |
||||
|
public bool IsEnabled { get; set; } |
||||
|
} |
||||
@ -0,0 +1,35 @@ |
|||||
|
using LINGYUN.Abp.IP.Location; |
||||
|
using Microsoft.Extensions.Options; |
||||
|
using System; |
||||
|
using System.Threading.Tasks; |
||||
|
using Volo.Abp.Auditing; |
||||
|
|
||||
|
namespace LINGYUN.Abp.AuditLogging.IP.Location; |
||||
|
public class IPLocationAuditingStore : AuditingStore |
||||
|
{ |
||||
|
private readonly AbpAuditLoggingIPLocationOptions _options; |
||||
|
private readonly IIPLocationResolver _iPLocationResolver; |
||||
|
public IPLocationAuditingStore( |
||||
|
IOptionsMonitor<AbpAuditLoggingIPLocationOptions> options, |
||||
|
IIPLocationResolver iPLocationResolver, |
||||
|
IAuditLogManager manager) |
||||
|
: base(manager) |
||||
|
{ |
||||
|
_options = options.CurrentValue; |
||||
|
_iPLocationResolver = iPLocationResolver; |
||||
|
} |
||||
|
|
||||
|
public async override Task SaveAsync(AuditLogInfo auditInfo) |
||||
|
{ |
||||
|
if (_options.IsEnabled && !auditInfo.ClientIpAddress.IsNullOrWhiteSpace()) |
||||
|
{ |
||||
|
var result = await _iPLocationResolver.ResolveAsync(auditInfo.ClientIpAddress); |
||||
|
|
||||
|
if (result.Location?.Remarks?.IsNullOrWhiteSpace() == false) |
||||
|
{ |
||||
|
auditInfo.ExtraProperties.Add("Location", $"{result.Location.Remarks}"); |
||||
|
} |
||||
|
} |
||||
|
await base.SaveAsync(auditInfo); |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,37 @@ |
|||||
|
using LINGYUN.Abp.IP.Location; |
||||
|
using Microsoft.Extensions.Options; |
||||
|
using System; |
||||
|
using System.Threading.Tasks; |
||||
|
using Volo.Abp.SecurityLog; |
||||
|
|
||||
|
namespace LINGYUN.Abp.AuditLogging.IP.Location; |
||||
|
|
||||
|
public class IPLocationSecurityLogStore : SecurityLogStore |
||||
|
{ |
||||
|
private readonly AbpAuditLoggingIPLocationOptions _options; |
||||
|
private readonly IIPLocationResolver _iPLocationResolver; |
||||
|
public IPLocationSecurityLogStore( |
||||
|
IOptionsMonitor<AbpAuditLoggingIPLocationOptions> options, |
||||
|
IIPLocationResolver iPLocationResolver, |
||||
|
ISecurityLogManager manager) |
||||
|
: base(manager) |
||||
|
{ |
||||
|
_options = options.CurrentValue; |
||||
|
_iPLocationResolver = iPLocationResolver; |
||||
|
} |
||||
|
|
||||
|
public async override Task SaveAsync(SecurityLogInfo securityLogInfo) |
||||
|
{ |
||||
|
if (_options.IsEnabled && !securityLogInfo.ClientIpAddress.IsNullOrWhiteSpace()) |
||||
|
{ |
||||
|
var result = await _iPLocationResolver.ResolveAsync(securityLogInfo.ClientIpAddress); |
||||
|
|
||||
|
if (result.Location?.Remarks?.IsNullOrWhiteSpace() == false) |
||||
|
{ |
||||
|
securityLogInfo.ExtraProperties.Add("Location", $"{result.Location.Remarks}"); |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
await base.SaveAsync(securityLogInfo); |
||||
|
} |
||||
|
} |
||||
@ -1,5 +0,0 @@ |
|||||
namespace LINGYUN.Abp.AuditLogging.IP2Region; |
|
||||
public class AbpAuditLoggingIP2RegionOptions |
|
||||
{ |
|
||||
public bool IsEnabled { get; set; } |
|
||||
} |
|
||||
@ -1,34 +0,0 @@ |
|||||
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); |
|
||||
} |
|
||||
} |
|
||||
@ -1,36 +0,0 @@ |
|||||
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,3 @@ |
|||||
|
<Weavers xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="FodyWeavers.xsd"> |
||||
|
<ConfigureAwait ContinueOnCapturedContext="false" /> |
||||
|
</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,21 @@ |
|||||
|
<Project Sdk="Microsoft.NET.Sdk"> |
||||
|
|
||||
|
<Import Project="..\..\..\..\configureawait.props" /> |
||||
|
<Import Project="..\..\..\..\common.props" /> |
||||
|
|
||||
|
<PropertyGroup> |
||||
|
<TargetFrameworks>netstandard2.0;netstandard2.1;net8.0</TargetFrameworks> |
||||
|
<AssemblyName>LINGYUN.Abp.IP.Location</AssemblyName> |
||||
|
<PackageId>LINGYUN.Abp.IP.Location</PackageId> |
||||
|
<GenerateAssemblyConfigurationAttribute>false</GenerateAssemblyConfigurationAttribute> |
||||
|
<GenerateAssemblyCompanyAttribute>false</GenerateAssemblyCompanyAttribute> |
||||
|
<GenerateAssemblyProductAttribute>false</GenerateAssemblyProductAttribute> |
||||
|
<Nullable>enable</Nullable> |
||||
|
<RootNamespace /> |
||||
|
</PropertyGroup> |
||||
|
|
||||
|
<ItemGroup> |
||||
|
<PackageReference Include="Volo.Abp.Core" /> |
||||
|
</ItemGroup> |
||||
|
|
||||
|
</Project> |
||||
@ -0,0 +1,12 @@ |
|||||
|
using Microsoft.Extensions.DependencyInjection; |
||||
|
using Volo.Abp.Modularity; |
||||
|
|
||||
|
namespace LINGYUN.Abp.IP.Location; |
||||
|
|
||||
|
public class AbpIPLocationModule : AbpModule |
||||
|
{ |
||||
|
public override void ConfigureServices(ServiceConfigurationContext context) |
||||
|
{ |
||||
|
context.Services.AddSingleton<ICurrentIPLocationAccessor>(AsyncLocalCurrentIPLocationAccessor.Instance); |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,14 @@ |
|||||
|
using JetBrains.Annotations; |
||||
|
using System.Collections.Generic; |
||||
|
|
||||
|
namespace LINGYUN.Abp.IP.Location; |
||||
|
public class AbpIPLocationResolveOptions |
||||
|
{ |
||||
|
[NotNull] |
||||
|
public List<IIPLocationResolveContributor> IPLocationResolvers { get; } |
||||
|
|
||||
|
public AbpIPLocationResolveOptions() |
||||
|
{ |
||||
|
IPLocationResolvers = new List<IIPLocationResolveContributor>(); |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,19 @@ |
|||||
|
using System.Threading; |
||||
|
|
||||
|
namespace LINGYUN.Abp.IP.Location; |
||||
|
public class AsyncLocalCurrentIPLocationAccessor : ICurrentIPLocationAccessor |
||||
|
{ |
||||
|
public static AsyncLocalCurrentIPLocationAccessor Instance { get; } = new(); |
||||
|
|
||||
|
public IPLocation? Current { |
||||
|
get => _currentScope.Value; |
||||
|
set => _currentScope.Value = value; |
||||
|
} |
||||
|
|
||||
|
private readonly AsyncLocal<IPLocation?> _currentScope; |
||||
|
|
||||
|
private AsyncLocalCurrentIPLocationAccessor() |
||||
|
{ |
||||
|
_currentScope = new AsyncLocal<IPLocation?>(); |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,40 @@ |
|||||
|
using System; |
||||
|
using Volo.Abp; |
||||
|
using Volo.Abp.DependencyInjection; |
||||
|
|
||||
|
namespace LINGYUN.Abp.IP.Location; |
||||
|
public class CurrentIPLocation : ICurrentIPLocation, ITransientDependency |
||||
|
{ |
||||
|
public string? Country => _currentIPLocationAccessor.Current?.Country; |
||||
|
|
||||
|
public string? Province => _currentIPLocationAccessor.Current?.Province; |
||||
|
|
||||
|
public string? City => _currentIPLocationAccessor.Current?.City; |
||||
|
|
||||
|
public string? Remarks => _currentIPLocationAccessor.Current?.Remarks; |
||||
|
|
||||
|
|
||||
|
private readonly ICurrentIPLocationAccessor _currentIPLocationAccessor; |
||||
|
|
||||
|
public CurrentIPLocation(ICurrentIPLocationAccessor currentIPLocationAccessor) |
||||
|
{ |
||||
|
_currentIPLocationAccessor = currentIPLocationAccessor; |
||||
|
} |
||||
|
|
||||
|
public IDisposable Change(IPLocation? location = null) |
||||
|
{ |
||||
|
return SetCurrent(location); |
||||
|
} |
||||
|
|
||||
|
private IDisposable SetCurrent(IPLocation? location = null) |
||||
|
{ |
||||
|
var parentScope = _currentIPLocationAccessor.Current; |
||||
|
_currentIPLocationAccessor.Current = location; |
||||
|
|
||||
|
return new DisposeAction<ValueTuple<ICurrentIPLocationAccessor, IPLocation?>>(static (state) => |
||||
|
{ |
||||
|
var (currentIPLocationAccessor, parentScope) = state; |
||||
|
currentIPLocationAccessor.Current = parentScope; |
||||
|
}, (_currentIPLocationAccessor, parentScope)); |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,15 @@ |
|||||
|
using System; |
||||
|
|
||||
|
namespace LINGYUN.Abp.IP.Location; |
||||
|
public interface ICurrentIPLocation |
||||
|
{ |
||||
|
string? Country { get; } |
||||
|
|
||||
|
string? Province { get; } |
||||
|
|
||||
|
string? City { get; } |
||||
|
|
||||
|
string? Remarks { get; } |
||||
|
|
||||
|
IDisposable Change(IPLocation? location = null); |
||||
|
} |
||||
@ -0,0 +1,5 @@ |
|||||
|
namespace LINGYUN.Abp.IP.Location; |
||||
|
public interface ICurrentIPLocationAccessor |
||||
|
{ |
||||
|
IPLocation? Current { get; set; } |
||||
|
} |
||||
@ -0,0 +1,11 @@ |
|||||
|
using Volo.Abp.DependencyInjection; |
||||
|
|
||||
|
namespace LINGYUN.Abp.IP.Location; |
||||
|
public interface IIPLocationResolveContext : IServiceProviderAccessor |
||||
|
{ |
||||
|
string IpAddress { get; } |
||||
|
|
||||
|
IPLocation? Location { get; set; } |
||||
|
|
||||
|
bool Handled { get; set; } |
||||
|
} |
||||
@ -0,0 +1,9 @@ |
|||||
|
using System.Threading.Tasks; |
||||
|
|
||||
|
namespace LINGYUN.Abp.IP.Location; |
||||
|
public interface IIPLocationResolveContributor |
||||
|
{ |
||||
|
string Name { get; } |
||||
|
|
||||
|
Task ResolveAsync(IIPLocationResolveContext context); |
||||
|
} |
||||
@ -0,0 +1,9 @@ |
|||||
|
using JetBrains.Annotations; |
||||
|
using System.Threading.Tasks; |
||||
|
|
||||
|
namespace LINGYUN.Abp.IP.Location; |
||||
|
public interface IIPLocationResolver |
||||
|
{ |
||||
|
[NotNull] |
||||
|
Task<IPLocationResolveResult> ResolveAsync(string ipAddress); |
||||
|
} |
||||
@ -0,0 +1,19 @@ |
|||||
|
namespace LINGYUN.Abp.IP.Location; |
||||
|
public class IPLocation |
||||
|
{ |
||||
|
public string? Country { get; } |
||||
|
public string? Province { get;} |
||||
|
public string? City { get; } |
||||
|
public string? Remarks { get; set; } |
||||
|
public IPLocation( |
||||
|
string? country = null, |
||||
|
string? province = null, |
||||
|
string? city = null, |
||||
|
string? remarks = null) |
||||
|
{ |
||||
|
Country = country; |
||||
|
Province = province; |
||||
|
City = city; |
||||
|
Remarks = remarks; |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,24 @@ |
|||||
|
using System; |
||||
|
|
||||
|
namespace LINGYUN.Abp.IP.Location; |
||||
|
public class IPLocationResolveContext : IIPLocationResolveContext |
||||
|
{ |
||||
|
public IServiceProvider ServiceProvider { get; } |
||||
|
|
||||
|
public string IpAddress { get; } |
||||
|
|
||||
|
public IPLocation? Location { get; set; } |
||||
|
|
||||
|
public bool Handled { get; set; } |
||||
|
|
||||
|
public bool HasResolvedIPLocation() |
||||
|
{ |
||||
|
return Handled || Location != null; |
||||
|
} |
||||
|
|
||||
|
public IPLocationResolveContext(string ipAddress, IServiceProvider serviceProvider) |
||||
|
{ |
||||
|
IpAddress = ipAddress; |
||||
|
ServiceProvider = serviceProvider; |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,9 @@ |
|||||
|
using System.Threading.Tasks; |
||||
|
|
||||
|
namespace LINGYUN.Abp.IP.Location; |
||||
|
public abstract class IPLocationResolveContributorBase : IIPLocationResolveContributor |
||||
|
{ |
||||
|
public abstract string Name { get; } |
||||
|
|
||||
|
public abstract Task ResolveAsync(IIPLocationResolveContext context); |
||||
|
} |
||||
@ -0,0 +1,14 @@ |
|||||
|
using System.Collections.Generic; |
||||
|
|
||||
|
namespace LINGYUN.Abp.IP.Location; |
||||
|
public class IPLocationResolveResult |
||||
|
{ |
||||
|
public IPLocation? Location { get; set; } |
||||
|
|
||||
|
public List<string> AppliedResolvers { get; } |
||||
|
|
||||
|
public IPLocationResolveResult() |
||||
|
{ |
||||
|
AppliedResolvers = new List<string>(); |
||||
|
} |
||||
|
} |
||||
@ -0,0 +1,43 @@ |
|||||
|
using Microsoft.Extensions.DependencyInjection; |
||||
|
using Microsoft.Extensions.Options; |
||||
|
using System; |
||||
|
using System.Threading.Tasks; |
||||
|
using Volo.Abp.DependencyInjection; |
||||
|
|
||||
|
namespace LINGYUN.Abp.IP.Location; |
||||
|
public class IPLocationResolver : IIPLocationResolver, ITransientDependency |
||||
|
{ |
||||
|
private readonly IServiceProvider _serviceProvider; |
||||
|
private readonly AbpIPLocationResolveOptions _options; |
||||
|
|
||||
|
public IPLocationResolver(IOptions<AbpIPLocationResolveOptions> options, IServiceProvider serviceProvider) |
||||
|
{ |
||||
|
_serviceProvider = serviceProvider; |
||||
|
_options = options.Value; |
||||
|
} |
||||
|
|
||||
|
public virtual async Task<IPLocationResolveResult> ResolveAsync(string ipAddress) |
||||
|
{ |
||||
|
var result = new IPLocationResolveResult(); |
||||
|
|
||||
|
using (var serviceScope = _serviceProvider.CreateScope()) |
||||
|
{ |
||||
|
var context = new IPLocationResolveContext(ipAddress, serviceScope.ServiceProvider); |
||||
|
|
||||
|
foreach (var ipLocationResolver in _options.IPLocationResolvers) |
||||
|
{ |
||||
|
await ipLocationResolver.ResolveAsync(context); |
||||
|
|
||||
|
result.AppliedResolvers.Add(ipLocationResolver.Name); |
||||
|
|
||||
|
if (context.HasResolvedIPLocation()) |
||||
|
{ |
||||
|
result.Location = context.Location; |
||||
|
break; |
||||
|
} |
||||
|
} |
||||
|
} |
||||
|
|
||||
|
return result; |
||||
|
} |
||||
|
} |
||||
@ -1,14 +0,0 @@ |
|||||
using System.Threading.Tasks; |
|
||||
|
|
||||
namespace LINGYUN.Abp.IP2Region; |
|
||||
public interface IIpLocationInfoProvider |
|
||||
{ |
|
||||
/// <summary>
|
|
||||
/// 通过ip地址获取地理信息
|
|
||||
/// </summary>
|
|
||||
/// <param name="ipAddress">ip地址</param>
|
|
||||
/// <returns>
|
|
||||
/// 如果解析成功返回地理信息,否则返回null
|
|
||||
/// </returns>
|
|
||||
Task<LocationInfo?> GetLocationInfoAsync(string ipAddress); |
|
||||
} |
|
||||
@ -0,0 +1,68 @@ |
|||||
|
using IP2Region.Net.Abstractions; |
||||
|
using LINGYUN.Abp.IP.Location; |
||||
|
using Microsoft.Extensions.DependencyInjection; |
||||
|
using System; |
||||
|
using System.Threading.Tasks; |
||||
|
|
||||
|
namespace LINGYUN.Abp.IP2Region; |
||||
|
public class IP2RegionIPLocationResolveContributorBase : IPLocationResolveContributorBase |
||||
|
{ |
||||
|
public const string ContributorName = "IP2Region"; |
||||
|
public override string Name => ContributorName; |
||||
|
|
||||
|
public override Task ResolveAsync(IIPLocationResolveContext context) |
||||
|
{ |
||||
|
var searcher = context.ServiceProvider.GetRequiredService<ISearcher>(); |
||||
|
|
||||
|
var region = searcher.Search(context.IpAddress); |
||||
|
|
||||
|
if (string.IsNullOrWhiteSpace(region)) |
||||
|
{ |
||||
|
return Task.CompletedTask; |
||||
|
} |
||||
|
|
||||
|
var regions = region!.Split('|'); |
||||
|
// | 0 | 1 | 2 |3| 4 | 5 | 6 |
|
||||
|
// 39.128.0.0|39.128.31.255|中国|0|云南省|昆明市|移动
|
||||
|
// regions:
|
||||
|
// 中国 0 云南省 昆明市 移动
|
||||
|
|
||||
|
var ipLocation = new IPLocation( |
||||
|
regions.Length >= 1 && !string.Equals(regions[0], "0") ? regions[0] : null, |
||||
|
regions.Length >= 3 && !string.Equals(regions[2], "0") ? regions[2] : null, |
||||
|
regions.Length >= 4 && !string.Equals(regions[3], "0") ? regions[3] : null); |
||||
|
|
||||
|
// 36.133.108.0|36.133.119.255|中国|0|重庆|重庆市|移动
|
||||
|
if (!ipLocation.Province.IsNullOrWhiteSpace() && !ipLocation.City.IsNullOrWhiteSpace()) |
||||
|
{ |
||||
|
if (ipLocation.Province.Length < ipLocation.City.Length && |
||||
|
ipLocation.City.StartsWith(ipLocation.Province, StringComparison.InvariantCultureIgnoreCase)) |
||||
|
{ |
||||
|
// 重庆市
|
||||
|
ipLocation.Remarks = $"{ipLocation.City}"; |
||||
|
} |
||||
|
// 111.26.31.0|111.26.31.127|中国|0|吉林省|吉林市|移动
|
||||
|
else |
||||
|
{ |
||||
|
// 吉林省吉林市
|
||||
|
ipLocation.Remarks = $"{ipLocation.Province}{ipLocation.City}"; |
||||
|
} |
||||
|
} |
||||
|
// 220.246.0.0|220.246.255.255|中国|0|香港|0|电讯盈科
|
||||
|
else if (!ipLocation.Country.IsNullOrWhiteSpace() && !ipLocation.Province.IsNullOrWhiteSpace()) |
||||
|
{ |
||||
|
// 中国香港
|
||||
|
ipLocation.Remarks = $"{ipLocation.Country}{ipLocation.Province}"; |
||||
|
} |
||||
|
// 220.247.4.0|220.247.31.255|日本|0|0|0|0
|
||||
|
else |
||||
|
{ |
||||
|
// 日本
|
||||
|
ipLocation.Remarks = $"{ipLocation.Country}"; |
||||
|
} |
||||
|
|
||||
|
context.Location = ipLocation; |
||||
|
|
||||
|
return Task.CompletedTask; |
||||
|
} |
||||
|
} |
||||
@ -1,68 +0,0 @@ |
|||||
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); |
|
||||
} |
|
||||
} |
|
||||
@ -1,8 +0,0 @@ |
|||||
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; } |
|
||||
} |
|
||||
Loading…
Reference in new issue