@iEricLee 创建时间 : 2023-06-28 15:18:40 最后修改时间 : 2023-06-28 15:31:49
来自 ABP Framework 研习社(群号:726299208)群友 @JUYO
的提问:
在 ABP Framework 审计日志和安全日志中会记录客端IP地址,为了验证是不是框架本身Bug,查看生产环境数据库 AbpSecurityLogs
表中的记录:
其中 ClientIpAddress
列记录的IP地址是正常的。
接下来,对问题进行分析:
IP地址信息保存在HTTP上下文的请求中,所以要获取IP地址信息首先要获取HTTP上下文 HttpContext
。
在 WebForms 和 ASP.NET MVC WEB应用程序中可以直接通过 HttpContextCurrent.Request
获取请求。
示例:在 ASP.NET MVC 中获取 IP 地址信息
var ip = HttpContext.Current.Request.UserHostAddress;
在 ASP.NET Core MVC WEB应用程序中以上方式不起作用,需要通过 IHttpContextAccessor
来获取HTTP上下文。
ABP Framework 基于 .NE Core 构建,所以,在应用层获取客户端IP地址,只需要在应用服务类中的构造函数中注入接口 IHttpContextAccessor
,获取其实例。
示例:在应用服务中获取IP地址信息
using Microsoft.AspNetCore.Http;
public class IpAddressAppService{
private readonly IHttpContextAccessor httpContextAccessor;
public IpAddressAppService(IHttpContextAccessor httpContextAccessor)
{
this.httpContextAccessor = httpContextAccessor;
}
public string GetClientIpAddress()
{
return httpContextAccessor.HttpContext?.Connection.RemoteIpAddress.ToString();
}
}
在 .NET Core 中使用构造函数注入服务之前,需要先进行服务注册,否则无法获取服务实例。如果 IHttpContextAccessor
不可用,则说明并没有注册该服务。
最简单的方式,直接手动注册。通常是在启动程序模块定义类中注册,这样除了在应用服务类使用之外,还可以在控制器类中使用。
实例:在启动程序模块类中注册 IHttpContextAccessor
接口
public class AppModule : AbpModule
{
public override void ConfigureServices(ServiceConfigurationContext context)
{
//...
context.Services.TryAddSingleton<IHttpContextAccessor, HttpContextAccessor>();
}
}
通过以上设置,就可以在构造函数中正常获取 IHttpContextAccessor
服务了。
正常情况下,在 ABP Framework 中不需要手动注册 IHttpContextAccessor
,因为在 Volo.Abp.AspNetCore
模块定义类中进行了服务注册:
private static void AddAspNetServices(IServiceCollection services)
{
services.AddHttpContextAccessor();
}
AddHttpContextAccessor
是 .NET Core 程序集 Microsoft.AspNetCore.Http.dll
中为 IServiceCollection
提供的一个扩展方法,该扩展方法用来注册 IHttpContextAccessor
服务,查看该方法源码,可以看到其内部实现也是使用上述手动注册代码:
public static IServiceCollection AddHttpContextAccessor(this IServiceCollection services)
{
ArgumentNullException.ThrowIfNull(services);
services.TryAddSingleton<IHttpContextAccessor, HttpContextAccessor>();
return services;
}
所以,如果使用 ABP Framework 则只需要对 Volo.Abp.AspNetCore
模块直接或间接依赖即可。
如果在应用服务层中不能正常使用 IHttpContextAccessor
,请检查在应用程序模块类中是否已经添加对 Volo.Abp.AspNetCore
模块的依赖。
在 ABP Framework 中定义了 IWebClientInfoProvider
接口,提供获取 IP地址属性 ClientIpAddress
以及 浏览器信息属性 BrowserInfo
。
接口定义和实现代码位于 Volo.Abp.AspNetCore
程序集,默认实现为HttpContextWebClientInfoProvider
,该实现内部也是通过 IHttpContextAccessor
获取IP地址。
因此,在需要获取客户端IP地址和浏览器信息 应该统一使用 IWebClientInfoProvider
接口。
同样,在 ABP Framework 框架中,审计日志和安全日志等功能统一采用该接口获取IP地址信息:
- 审计日志提供程序
AspNetCoreAuditLogContributor
- 安全日志管理器
AspNetCoreSecurityLogManager