如何在ASP.NET CORE中获取客户端IP地址?


200

您能否让我知道在使用MVC 6 Request.ServerVariables["REMOTE_ADDR"]无法正常工作时如何在ASP.NET中获取客户端IP地址。


范例:httpContext.GetFeature<IHttpConnectionFeature>().RemoteIpAddress
Kiran Challa

保留原因可在问题的底部找到,“对于这种格式,答案可能太多,或者好的答案将太长。请添加详细信息以缩小答案范围或找出可以在其中回答的问题几段。”
凯文·布朗

12
我认为答案还不够长。在旧版本的MVC中,这很简单。我只是问如何在最新的Beta版本中进行操作。其次,如果答案很多,为什么没有人将我指向其中之一。实际上,MVC 6是beta版,我认为他们在持有它之前甚至没有正确阅读问题。
eadam 2015年

编辑您的问题,以显示更多您尝试过的内容以及清晰的输入/输出。不要只是抱怨你的问题没有得到至少关闭试图改善它。

10
只有来自同一领域的程序员才应该解决这个问题。在asp.net 5.0中工作的任何人都可以在不到一秒钟的时间内知道我的要求。其余的人只是在发布一个简单的问题而惩罚我。
eadam 2015年

Answers:


269

API已更新。不确定何时更改,但是据达米安·爱德华兹Damien Edwards)所说,您现在可以执行以下操作:

var remoteIpAddress = request.HttpContext.Connection.RemoteIpAddress;

9
当我在IIS上发布他的网站并将其记录在文件中时,这RemoteIpAddress始终null是我的选择。
A-Sharabiani '16

3
看来该问题已在rc 2中解决
乔恩(Jon)

12
即使我进行远程连接,我也总是得到127.0.0.1
frostymarvelous

32
这为我返回的是IPv6格式的“ :: 1”。其他人如何看待127.0.0.1?
Derek Greer

4
是否还有其他人返回了其IIS服务器的本地IP地址?
dave317 '18

72

在project.json中将依赖项添加到:

"Microsoft.AspNetCore.HttpOverrides": "1.0.0"

Startup.cs中的Configure()方法中,添加:

  app.UseForwardedHeaders(new ForwardedHeadersOptions
        {
            ForwardedHeaders = ForwardedHeaders.XForwardedFor |
            ForwardedHeaders.XForwardedProto
        });  

而且当然:

using Microsoft.AspNetCore.HttpOverrides;

然后,我可以使用以下命令获取ip:

Request.HttpContext.Connection.RemoteIpAddress

就我而言,在VS中进行调试时,我总是拥有IpV6本地主机,但是在IIS上部署时,我总是具有远程IP。

一些有用的链接: 如何在ASP.NET CORE中获取客户端IP地址?并且RemoteIpAddress始终为null

::1也许是因为:

IIS处的连接终止,然后将其转发到v.next Web服务器Kestrel,因此与Web服务器的连接确实来自本地主机。(https://stackoverflow.com/a/35442401/5326387


6
这是正确的答案,在反向代理的官方文档中也有记录:docs.microsoft.com/en-us/aspnet/core/host-and-deploy/…–
Melvyn

8
需要指出的是,需要在app.UseAuthentication()之前添加“ app.UseForwardedHeaders ...”;行,以防您使用身份验证
netfed

1
这工作得很好,我已经在本地托管的IIS和Azure上进行了测试。在两个地方都可以使用。
ThomasCle

72

可以添加一些后备逻辑来处理负载均衡器的存在。

另外,通过检查,X-Forwarded-For即使没有负载均衡器,报头也可能会被设置(可能是由于附加的Kestrel层?):

public string GetRequestIP(bool tryUseXForwardHeader = true)
{
    string ip = null;

    // todo support new "Forwarded" header (2014) https://en.wikipedia.org/wiki/X-Forwarded-For

    // X-Forwarded-For (csv list):  Using the First entry in the list seems to work
    // for 99% of cases however it has been suggested that a better (although tedious)
    // approach might be to read each IP from right to left and use the first public IP.
    // http://stackoverflow.com/a/43554000/538763
    //
    if (tryUseXForwardHeader)
        ip = GetHeaderValueAs<string>("X-Forwarded-For").SplitCsv().FirstOrDefault();

    // RemoteIpAddress is always null in DNX RC1 Update1 (bug).
    if (ip.IsNullOrWhitespace() && _httpContextAccessor.HttpContext?.Connection?.RemoteIpAddress != null)
        ip = _httpContextAccessor.HttpContext.Connection.RemoteIpAddress.ToString();

    if (ip.IsNullOrWhitespace())
        ip = GetHeaderValueAs<string>("REMOTE_ADDR");

    // _httpContextAccessor.HttpContext?.Request?.Host this is the local host.

    if (ip.IsNullOrWhitespace())
        throw new Exception("Unable to determine caller's IP.");

    return ip;
}

public T GetHeaderValueAs<T>(string headerName)
{
    StringValues values;

    if (_httpContextAccessor.HttpContext?.Request?.Headers?.TryGetValue(headerName, out values) ?? false)
    {
        string rawValues = values.ToString();   // writes out as Csv when there are multiple.

        if (!rawValues.IsNullOrWhitespace())
            return (T)Convert.ChangeType(values.ToString(), typeof(T));
    }
    return default(T);
}

public static List<string> SplitCsv(this string csvList, bool nullOrWhitespaceInputReturnsNull = false)
{
    if (string.IsNullOrWhiteSpace(csvList))
        return nullOrWhitespaceInputReturnsNull ? null : new List<string>();

    return csvList
        .TrimEnd(',')
        .Split(',')
        .AsEnumerable<string>()
        .Select(s => s.Trim())
        .ToList();
}

public static bool IsNullOrWhitespace(this string s)
{
    return String.IsNullOrWhiteSpace(s);
}

假设_httpContextAccessor是通过DI提供的。


2
这是正确的答案。没有唯一的方法来获取IP地址,特别是当您的应用程序位于Nginx,负载均衡器或类似设备之后时。谢谢!
2016年

@feu之类的,因为AspNetCore可以使用诸如X-Forwarded-For之类的标头覆盖RemoteIpAddress属性。
马克·洛佩兹

@crokusek ...试图适应您的解决方案,但是VS强迫我使用静态封装此代码的类。您的Web应用程序项目中或解决方案的类库中是否有此代码?
dinotom

前两个方法应该在提供__httpContextAccessor的实例中(或对其进行调整)。后两个字符串方法是从单独的静态扩展类中提取的。
crokusek

这是一个很好的解决方案,尤其是当您的应用程序使用Kestrel并由Linux上的Nginx托管时。
蒂莫西·马卡里亚

16

您可以使用IHttpConnectionFeature获取此信息。

var remoteIpAddress = httpContext.GetFeature<IHttpConnectionFeature>()?.RemoteIpAddress;

感谢你的回答!
eadam

2
它适用于Kestrel托管吗?在我的演示中,httpContext.GetFeature<IHttpConnectionFeature>()始终是null
杰里·比安

2
@JerryBian根据此文档:github.com/aspnet/Docs/blob/master/aspnet/fundamentals/…,Kestrel还不支持IHttpConnectionFeature。
qbik

@JerryBian现在是
David Peden

一定已弃用-@feradz版本在RC-1中对我有效
菲亚特

12
var remoteIpAddress = HttpContext.Features.Get<IHttpConnectionFeature>()?.RemoteIpAddress;

6
太复杂了。MVC已经在内部对其进行了调用,并将其置于之下HttpContext.Connection.RemoteIpAddress
弗雷德(Fred)2016年

@Fred-您的版本在RC-1中为我返回null-IIS和Kestrel
菲亚特

7

在ASP.NET 2.1中,在StartUp.cs中添加以下服务:

services.AddHttpContextAccessor();
services.TryAddSingleton<IActionContextAccessor, ActionContextAccessor>();

然后做3步:

  1. 在您的MVC控制器中定义一个变量

    private IHttpContextAccessor _accessor;
  2. DI进入控制器的构造函数

    public SomeController(IHttpContextAccessor accessor)
    {
        _accessor = accessor;
    }
  3. 检索IP地址

    _accessor.HttpContext.Connection.RemoteIpAddress.ToString()

这是完成的方式。


2
这给了我:: 1。本地主机上的Asp.Net Core 2.2。
斯蒂安,

::1在IPv6中是localhost。相当于127.0.0.1
Andy

6

这对我有用(DotNetCore 2.1)

[HttpGet]
public string Get() 
{
    var remoteIpAddress = HttpContext.Connection.RemoteIpAddress;
    return remoteIpAddress.ToString();
}

3

就我而言,我拥有在DigitalOcean上运行的DotNet Core 2.2 Web App,并使用docker和nginx作为反向代理。使用Startup.cs中的这段代码,我可以获得客户端IP

app.UseForwardedHeaders(new ForwardedHeadersOptions
        {
            ForwardedHeaders = ForwardedHeaders.All,
            RequireHeaderSymmetry = false,
            ForwardLimit = null,
            KnownNetworks = { new IPNetwork(IPAddress.Parse("::ffff:172.17.0.1"), 104) }
        });

:: ffff:172.17.0.1是我在使用之前获得的IP

Request.HttpContext.Connection.RemoteIpAddress.ToString();

2

首先,在.Net Core 1.0中添加using Microsoft.AspNetCore.Http.Features;到控制器,然后在相关方法内部:

var ip = HttpContext.Features.Get<IHttpConnectionFeature>()?.RemoteIpAddress?.ToString();

我读了其他一些未能编译的答案,因为它使用的是小写的httpContext,导致VS使用Microsoft.AspNetCore.Http(而不是适当的用法)或HttpContext添加(编译器也会误导)。


2

在.net核心中获取ipaddress和主机名

将此代码放入控制器

跟着这些步骤:

var addlist = Dns.GetHostEntry(Dns.GetHostName());
string GetHostName = addlist.HostName.ToString();
string GetIPV6 = addlist.AddressList[0].ToString();
string GetIPV4 = addlist.AddressList[1].ToString();

2

我发现,有些人发现您获得的IP地址是::: 1或0.0.0.1

之所以会出现此问题,是因为您尝试从自己的计算机上获取IP,以及C#试图返回IPv6的困惑。

因此,我实现了@Johna(https://stackoverflow.com/a/41335701/812720)和@David(https://stackoverflow.com/a/8597351/812720)的答案,感谢他们!

并在这里解决:

  1. 在您的引用(依赖项/包)中添加Microsoft.AspNetCore.HttpOverrides包

  2. 在Startup.cs中添加此行

    public void Configure(IApplicationBuilder app, IHostingEnvironment env)
    {
        // your current code
    
        // start code to add
        // to get ip address
        app.UseForwardedHeaders(new ForwardedHeadersOptions
        {
        ForwardedHeaders = ForwardedHeaders.XForwardedFor | ForwardedHeaders.XForwardedProto
        });
        // end code to add
    
    }
  3. 要获取IPAddress,请在您的任何Controller.cs中使用此代码

    IPAddress remoteIpAddress = Request.HttpContext.Connection.RemoteIpAddress;
    string result = "";
    if (remoteIpAddress != null)
    {
        // If we got an IPV6 address, then we need to ask the network for the IPV4 address 
        // This usually only happens when the browser is on the same machine as the server.
        if (remoteIpAddress.AddressFamily == System.Net.Sockets.AddressFamily.InterNetworkV6)
        {
            remoteIpAddress = System.Net.Dns.GetHostEntry(remoteIpAddress).AddressList
    .First(x => x.AddressFamily == System.Net.Sockets.AddressFamily.InterNetwork);
        }
        result = remoteIpAddress.ToString();
    }

现在您可以从remoteIpAddressresult获取IPv4地址


1

试试这个。

var host = Dns.GetHostEntry(Dns.GetHostName());
        foreach (var ip in host.AddressList)
        {
            if (ip.AddressFamily == AddressFamily.InterNetwork)
            {
                 ipAddress = ip.ToString();
            }
        }

0

在负载均衡器后面运行.NET core(3.1.4)IIS不能与其他建议的解决方案一起使用。

手动读取X-Forwarded-For标头确实如此。

IPAddress ip;
var headers = Request.Headers.ToList();
if (headers.Exists((kvp) => kvp.Key == "X-Forwarded-For"))
{
    // when running behind a load balancer you can expect this header
    var header = headers.First((kvp) => kvp.Key == "X-Forwarded-For").Value.ToString();
    ip = IPAddress.Parse(header);
}
else
{
    // this will always have a value (running locally in development won't have the header)
    ip = Request.HttpContext.Connection.RemoteIpAddress;
}

我正在使用托管捆绑包运行一个自包含的软件包。


0

在Ubuntu上的Traefik反向代理后面运行ASP.NET Core 2.1,我需要KnownProxies在安装官方Microsoft.AspNetCore.HttpOverrides软件包后设置其网关IP

        var forwardedOptions = new ForwardedHeadersOptions {
            ForwardedHeaders = ForwardedHeaders.XForwardedFor,
        };
        forwardedOptions.KnownProxies.Add(IPAddress.Parse("192.168.3.1"));
        app.UseForwardedHeaders(forwardedOptions);

根据文档,如果反向代理未在本地主机上运行,​​则这是必需的。该docker-compose.ymlTraefik已经分配了一个静态IP地址:

networks:
  my-docker-network:
    ipv4_address: 192.168.3.2

另外,应该足以确保在此处定义了已知的网络以在.NET Core中指定其网关。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.