如何在 ASP.NET Core 2.1 中获取客户端 IP 地址

Posted

技术标签:

【中文标题】如何在 ASP.NET Core 2.1 中获取客户端 IP 地址【英文标题】:How to get Client IP address in ASP.NET Core 2.1 【发布时间】:2018-06-30 15:57:12 【问题描述】:

我正在使用 Microsoft Visual Studio 2017 提供的 Angular 模板开发 ASP.Net Core 2.1。我的客户端应用程序运行良好。用户认证竞争后,我想启动存储客户端用户 IP 地址的用户会话管理。我已经在互联网上搜索过这个,但到目前为止还没有找到任何解决方案。

以下是我已经访问过的一些参考链接:

How do I get client IP address in ASP.NET CORE?

Get Client IP Address in ASP.NET Core 2.0

Get a user remote IP Address in ASP.Net Core

在我的 ValuesController.cs 中,我还尝试了以下代码:

private IHttpContextAccessor _accessor;

public ValuesController(IHttpContextAccessor accessor)

    _accessor = accessor;


public IEnumerable<string> Get()

    var ip = Request.HttpContext.Connection.RemoteIpAddress.ToString();
    return new string[]  ip, "value2" ;

其中 ip 变量我得到空值并出现此错误

Request.HttpContext.Connection.RemoteIpAddress.Address 抛出类型为“System.Net.Sockets.SocketException”的异常

请告诉我。

【问题讨论】:

如果你使用_accessor.HttpContext.Connection.RemoteIpAddress也是null吗? 您是否尝试通过 IP 地址来识别用户?那是不可靠的。您网站上的两个人在图书馆、咖啡店、酒店等处连接到公共 wifi 将具有相同的 IP 地址。 你怎么称呼这段代码?你应该可以在控制器中只做HttpContext.Connection.RemoteIpAddress。无需通过Request 或在那里使用 HttpContextAccessor。 如何解析远程ip地址与宿主环境的具体情况有很大关系docs.microsoft.com/en-us/aspnet/core/host-and-deploy/… @poke 你的解决方案在我的情况下不起作用。 【参考方案1】:

在您的Startup.cs 中,确保您有一个ConfigureServices 方法,传入IServiceCollection,然后将IHttpContextAccessor 注册为单例,如下所示:

public void ConfigureServices(IServiceCollection services)

    services.AddSingleton<IHttpContextAccessor, HttpContextAccessor>();

Startup.cs 文件中注册IHttpContextAccessor 后,您可以在控制器类中注入IHttpContextAccessor 并像这样使用它:

private IHttpContextAccessor _accessor;

public ValuesController(IHttpContextAccessor accessor)

    _accessor = accessor;


public IEnumerable<string> Get()

    var ip = _accessor.HttpContext?.Connection?.RemoteIpAddress?.ToString();
    return new string[]  ip, "value2" ;

【讨论】:

ToString 值对我来说是 "::1" 在 localhost 机器上运行时。 return new string[] ip, "value2" ;中的value2的目的是什么? value2 只是在这里返回以匹配初始问题中提供的代码,并且不用于检索客户端 IP 的任何目的。同样的块也可以写成如下:public string Get() return _accessor.HttpContext?.Connection?.RemoteIpAddress?.ToString(); 【参考方案2】:

可以使用以下代码:

services.Configure<ForwardedHeadersOptions>(options =>

    options.ForwardedHeaders = ForwardedHeaders.XForwardedFor | ForwardedHeaders.XForwardedProto;
);

string remoteIpAddress = HttpContext.Connection.RemoteIpAddress.MapToIPv4().ToString();
if (Request.Headers.ContainsKey("X-Forwarded-For"))
    remoteIpAddress = Request.Headers["X-Forwarded-For"];

【讨论】:

你的回答和使用有什么区别:app.UseForwardedHeaders(new ForwardedHeadersOptionsForwardedHeaders = ForwardedHeaders.XForwardedFor | ForwardedHeaders.XForwardedProto); ? @desmati,如果我不检查 Request.Headers.ContainsKey("X-Forwarded-For") ,即使我只使用 app.UseForwardedHeaders(new ForwardedHeadersOptionsForwardedHeaders = ForwardedHeaders.XForwardedFor | ForwardedHeaders.XForwardedProto); @Liam,我也有同样的问题。根据文章 docs.microsoft.com/en-us/aspnet/core/host-and-deploy/… ,它应该直接从 context.Connection.RemoteIpAddress 工作。不幸的是,我还必须从 context.Request.Headers[_xForwardedForHeader] 获取客户端 IP。 “x-forwarded-for”标头还可以包含托管它的网站的端口(例如 10.0.120:6529)。要删除它(假设它是 IPv4 地址),您可以使用以下命令来删除它:remoteIpAddress = Request.Headers["X-Forwarded-For"].ToString().Split(":")[0]; 【参考方案3】:

如果您的 Kestrel 位于 IIS 等反向代理之后,请确保转发包含客户端 IP 的标头。 这进入启动:

app.UseForwardedHeaders(new ForwardedHeadersOptionsForwardedHeaders = ForwardedHeaders.XForwardedFor | ForwardedHeaders.XForwardedProto);

【讨论】:

【参考方案4】:

如果我使用绑定地址 Localhost:5000,那么 IP 将返回为“::1”(Localhost IPv6 地址)。 如果我在 IP 地址上绑定我的 Webapi 并尝试从另一台客户端计算机访问它,我会在 API 响应中获得客户端的 IP 地址。 我相信不需要 HTTPAccessor。根据文档https://docs.microsoft.com/en-us/aspnet/core/host-and-deploy/proxy-load-balancer?view=aspnetcore-2.1,HttpContext.Connection.RemoteIpAddress 由 XForwardedFor 标头设置。

如果您的应用程序 (WEBAPI) 位于 nginx/Apache 反向代理之后,如果您未设置或处理 X-Forwarded-For Header,那么您总是会得到 Nulls 或 Reverse-Proxy Server 的 IP 地址。

上面的 GetHostEntry 与 HTTP 请求没有直接关系。 GetHostEntry 只是一个用于 API 编程的 NSLookup 工具,它只告诉您特定名称可访问的 IP 地址,但不会告诉您请求来自哪个 IP 地址到 WebApi。

希望有帮助

【讨论】:

【参考方案5】:

试试这个代码,

var ipAddress = HttpContext.Connection.RemoteIpAddress;

如果您在同一个 LAN 中有另一台计算机,请尝试与这台计算机连接,但使用用户 ip 而不是 localhost。否则,您将始终得到 ::1 结果。

【讨论】:

【参考方案6】:

花了一些时间搜索后,我找到了自己的问题答案。在这里,我还分享了源链接,从中可以获得我的答案和详细说明,以了解如何查询服务器以获取家庭地址和它支持的 IP 地址。

代码:

IPHostEntry heserver = Dns.GetHostEntry(Dns.GetHostName());
var ip = heserver.AddressList[2].ToString();

Source

这是我的另一个Question: How to access server variables in ASP.Net Core 2.x希望这对大家有帮助。

【讨论】:

我不确定是否理解。这很有趣,但在我看来,您的答案没有提供来自正在查询您的服务器的客户端的 client ip 地址,这是您的问题。 你的意思是说上面的代码没有返回客户端IP地址?也许你是对的,因为我使用的是 localhost,也许它会返回一个服务器 IP 地址。 是的,好像是来自服务端(应用的Host)的地址,对应服务端的DNS信息,所以可能和客户端完全无关。跨度> @Pac0 那么我现在能做什么呢?如何获取客户端 IP 地址? 我还是不知道,很遗憾。在我知道的所有情况下,HttpContext.Connection.RemoteIpAddress 都是可行的方法,但由于某种原因,它显然对你不起作用。【参考方案7】:

这对我有用 .Net Core 2.2:

IPHostEntry heserver = Dns.GetHostEntry(Dns.GetHostName());

var ipAddress = heserver.AddressList.ToList().Where(p => p.AddressFamily == System.Net.Sockets.AddressFamily.InterNetwork).FirstOrDefault().ToString();

【讨论】:

你能解释一下这是如何提供客户端IP地址的吗? 提供服务器IP而不是客户端IP

以上是关于如何在 ASP.NET Core 2.1 中获取客户端 IP 地址的主要内容,如果未能解决你的问题,请参考以下文章