如何在 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 地址的主要内容,如果未能解决你的问题,请参考以下文章

直接从令牌获取 JWT 声明,ASP Net Core 2.1

如何在 asp.net core 2.1 中使用自定义消息设置状态代码?

如何在 ASP.NET Core 2.1 中使用自动完成输入引发模式

如何在 ASP.NET Core 2.1 中的计时器上运行 BackgroundService

Asp.net core 2.1 - 如何服务多个角度应用程序?

如何在 ASP .NET Core 2.1 中将登录页面设为默认路由?