c# - 如何在ASP.NET中获取用户的客户端IP地址?




client ip-address (11)

我们有Request.UserHostAddress来获取ASP.NET中的IP地址,但这通常是用户的ISP的IP地址,而不是用户的机器IP地址,例如点击链接。 我怎样才能得到真正的IP地址?

例如,在Stack Overflow用户配置文件中,它是: “Last account activity:4 hours ago from 86.123.127.8” ,但我的机器IP地址有点不同。 堆栈溢出如何得到这个地址?

在某些网络系统中,出于某种目的进行IP地址检查。 例如,使用特定的IP地址,用户每24小时只能点击5次下载链接? 此IP地址应该是唯一的,不适用于拥有大量客户端或Internet用户的ISP。

我理解得好吗?


IP地址是“七层堆叠”中网络层的一部分。 网络层可以做​​任何想要处理的IP地址。 这就是代理服务器,NAT,中继或其他什么情况。

应用层不应以任何方式依赖IP地址。 特别是,IP地址并不意味着除了网络连接一端的标识符以外的任何标识符。 一旦连接关闭,您应该期望(同一用户的)IP地址发生变化。


尝试:

using System.Net;

public static string GetIpAddress()  // Get IP Address
{
    string ip = "";     
    IPHostEntry ipEntry = Dns.GetHostEntry(GetCompCode());
    IPAddress[] addr = ipEntry.AddressList;
    ip = addr[2].ToString();
    return ip;
}
public static string GetCompCode()  // Get Computer Name
{   
    string strHostName = "";
    strHostName = Dns.GetHostName();
    return strHostName;
}

你可以做的是存储你的用户的路由器IP以及转发的IP,并尝试使用这两个IP [外部公共和内部私有]来保证它的可靠性。 但是,几天之后,客户端可能会从路由器分配新的内部IP,但它会更可靠。


你还认为用户的IP地址是什么? 如果您想要网络适配器的IP地址,恐怕没有办法在Web应用程序中执行此操作。 如果你的用户在NAT或其他东西之后,你也不能得到IP。

更新 :虽然有些网站使用IP来限制用户(如rapidshare),但它们在NAT环境中无法正常工作。


如果您正在使用CloudFlare,则可以尝试此扩展方法

public static class IPhelper
{
    public static string GetIPAddress(this HttpRequest Request)
    {
        if (Request.Headers["CF-CONNECTING-IP"] != null) return Request.Headers["CF-CONNECTING-IP"].ToString();

        if (Request.ServerVariables["HTTP_X_FORWARDED_FOR"] != null) return Request.ServerVariables["HTTP_X_FORWARDED_FOR"].ToString();

        return Request.UserHostAddress;
    }
}

然后

string IPAddress = Request.GetIPAddress();

如果是c#这样看,很简单

string clientIp = (Request.ServerVariables["HTTP_X_FORWARDED_FOR"] ?? 
                   Request.ServerVariables["REMOTE_ADDR"]).Split(',')[0].Trim();

我想我应该与大家分享我的经验。 那么我在某些情况下看到REMOTE_ADDR不会让你找到你想要的东西。 例如,如果您在场景后面有负载均衡器,并且您尝试获取客户端的IP,那么您将遇到麻烦。 我用我的IP掩模软件检查了它,并且还与在不同大陆的同事们进行了检查。 所以这是我的解决方案。

当我想知道客户的知识产权时,我会尽力挑选所有可能的证据,以便确定它们是否独一无二:

在这里,我发现了另一个sever-var,如果你想获得客户端的确切IP,它可以帮助你。 所以我使用: HTTP_X_CLUSTER_CLIENT_IP

HTTP_X_CLUSTER_CLIENT_IP总是会为您提供客户端的确切IP。 在任何情况下,如果它不给你的价值,你应该寻找HTTP_X_FORWARDED_FOR,因为它是第二个最好的候选人,让你的客户端IP,然后REMOTE_ADDR var可能会或可能不会返回你的IP,但对我有所有这些三是我发现监控他们最好的东西。

我希望这可以帮助一些人。


正如其他人所说,你不能做你在问什么。 如果你描述你正试图解决的问题,也许有人可以帮忙? 例如,你是否想要唯一标识你的用户? 你可以使用cookie,或者使用会话ID而不是IP地址?

编辑你在服务器上看到的地址不应该是ISP的地址,因为你认为这将是一个巨大的范围。 家庭用户使用宽带的地址将是其路由器的地址,因此房屋内的每台设备都将显示在外部,因此路由器使用NAT来确保将流量正确路由到每个设备。 对于从办公室环境访问的用户,地址对于所有用户来说可能是相同的。 使用IP地址作为ID的站点有可能导致错误 - 您提供的示例是好的,它们往往会失败。 例如,我的办公室位于英国,突破点(我“出现”在互联网上)位于我们主要IT设施所在的另一个国家,所以从我的办公室我的IP地址似乎不在英国。 出于这个原因,我无法访问英国唯一的网络内容,例如BBC iPlayer)。 在任何时候,我的公司中会有数百甚至数千人似乎从同一个IP地址访问网络。

当你编写服务器代码时,你永远无法确定你所看到的IP地址是指什么。 有些用户喜欢这样。 有些人故意使用代理或VPN来进一步混淆你。

当你说你的机器地址与上显示的IP地址不同时,你如何找到你的机器地址? 如果你只是在本地使用ipconfig或类似的东西,我期望它会因为我上面列出的原因而不同。 如果你想仔细检查一下外界的想法,请看whatismyipaddress.com/

这个NAT上的Wikipedia链接将为您提供一些背景知识。


结合@Tony@mangokun的答案,我创建了以下扩展方法:

public static class RequestExtensions
{
    public static string GetIPAddress(this HttpRequest Request)
    {
        if (Request.Headers["CF-CONNECTING-IP"] != null) return Request.Headers["CF-CONNECTING-IP"].ToString();

        if (Request.ServerVariables["HTTP_X_FORWARDED_FOR"] != null)
        {
            string ipAddress = Request.ServerVariables["HTTP_X_FORWARDED_FOR"];

            if (!string.IsNullOrEmpty(ipAddress))
            {
                string[] addresses = ipAddress.Split(',');
                if (addresses.Length != 0)
                {
                    return addresses[0];
                }
            }
        }

        return Request.UserHostAddress;
    }
}

迄今为止的所有响应都考虑到非标准化但非常常见的X-Forwarded-For标头。 有一个标准化的Forwarded头,这是一个更难解析的头。 一些例子如下:

Forwarded: for="_gazonk"
Forwarded: For="[2001:db8:cafe::17]:4711"
Forwarded: for=192.0.2.60;proto=http;by=203.0.113.43
Forwarded: for=192.0.2.43, for=198.51.100.17

我写了一个在确定客户端IP地址时考虑这两个头部的类。

using System;
using System.Web;

namespace Util
{
    public static class IP
    {
        public static string GetIPAddress()
        {
            return GetIPAddress(new HttpRequestWrapper(HttpContext.Current.Request));
        }

        internal static string GetIPAddress(HttpRequestBase request)
        {
            // handle standardized 'Forwarded' header
            string forwarded = request.Headers["Forwarded"];
            if (!String.IsNullOrEmpty(forwarded))
            {
                foreach (string segment in forwarded.Split(',')[0].Split(';'))
                {
                    string[] pair = segment.Trim().Split('=');
                    if (pair.Length == 2 && pair[0].Equals("for", StringComparison.OrdinalIgnoreCase))
                    {
                        string ip = pair[1].Trim('"');

                        // IPv6 addresses are always enclosed in square brackets
                        int left = ip.IndexOf('['), right = ip.IndexOf(']');
                        if (left == 0 && right > 0)
                        {
                            return ip.Substring(1, right - 1);
                        }

                        // strip port of IPv4 addresses
                        int colon = ip.IndexOf(':');
                        if (colon != -1)
                        {
                            return ip.Substring(0, colon);
                        }

                        // this will return IPv4, "unknown", and obfuscated addresses
                        return ip;
                    }
                }
            }

            // handle non-standardized 'X-Forwarded-For' header
            string xForwardedFor = request.Headers["X-Forwarded-For"];
            if (!String.IsNullOrEmpty(xForwardedFor))
            {
                return xForwardedFor.Split(',')[0];
            }

            return request.UserHostAddress;
        }
    }
}

以下是我用来验证解决方案的一些单元测试:

using System.Collections.Specialized;
using System.Web;
using Microsoft.VisualStudio.TestTools.UnitTesting;

namespace UtilTests
{
    [TestClass]
    public class IPTests
    {
        [TestMethod]
        public void TestForwardedObfuscated()
        {
            var request = new HttpRequestMock("for=\"_gazonk\"");
            Assert.AreEqual("_gazonk", Util.IP.GetIPAddress(request));
        }

        [TestMethod]
        public void TestForwardedIPv6()
        {
            var request = new HttpRequestMock("For=\"[2001:db8:cafe::17]:4711\"");
            Assert.AreEqual("2001:db8:cafe::17", Util.IP.GetIPAddress(request));
        }

        [TestMethod]
        public void TestForwardedIPv4()
        {
            var request = new HttpRequestMock("for=192.0.2.60;proto=http;by=203.0.113.43");
            Assert.AreEqual("192.0.2.60", Util.IP.GetIPAddress(request));
        }

        [TestMethod]
        public void TestForwardedIPv4WithPort()
        {
            var request = new HttpRequestMock("for=192.0.2.60:443;proto=http;by=203.0.113.43");
            Assert.AreEqual("192.0.2.60", Util.IP.GetIPAddress(request));
        }

        [TestMethod]
        public void TestForwardedMultiple()
        {
            var request = new HttpRequestMock("for=192.0.2.43, for=198.51.100.17");
            Assert.AreEqual("192.0.2.43", Util.IP.GetIPAddress(request));
        }
    }

    public class HttpRequestMock : HttpRequestBase
    {
        private NameValueCollection headers = new NameValueCollection();

        public HttpRequestMock(string forwarded)
        {
            headers["Forwarded"] = forwarded;
        }

        public override NameValueCollection Headers
        {
            get { return this.headers; }
        }
    }
}

string IP = HttpContext.Current.Request.Params["HTTP_CLIENT_IP"] ?? HttpContext.Current.Request.UserHostAddress;




ip-address