Как получить IP-адрес клиента пользователя в ASP.NET?

У нас есть Request.UserHostAddress чтобы получить IP-адрес в ASP.NET, но обычно это IP-адрес интернет-провайдера пользователя, а не IP-адрес компьютера пользователя, который, например, щелкнул ссылку. Как я могу получить реальный IP-адрес?

Например, в профиле пользователя Stack Overflow это: "Последнее действие учетной записи: 4 часа назад с 86.123.127.8", но IP-адрес моего компьютера немного отличается. Как Stack Overflow получает этот адрес?

В некоторых веб-системах для некоторых целей выполняется проверка IP-адреса. Например, с определенным IP-адресом, может ли пользователь каждые пять часов нажимать на ссылки для скачивания всего 5 раз? Этот IP-адрес должен быть уникальным, а не для интернет-провайдера, который имеет огромный круг клиентов или пользователей Интернета.

Я хорошо понял?

21 ответ

Решение

Как говорили другие, вы не можете делать то, что просите. Если вы опишите проблему, которую пытаетесь решить, может, кто-то может помочь? Например, вы пытаетесь однозначно идентифицировать своих пользователей? Не могли бы вы использовать куки или идентификатор сессии вместо IP-адреса?

Изменить адрес, который вы видите на сервере, не должен быть адресом провайдера, так как вы говорите, что это будет огромный диапазон. Адрес домашнего пользователя в широкополосной сети будет адресом их маршрутизатора, поэтому каждое устройство в доме будет выглядеть одинаково снаружи, но маршрутизатор использует NAT для обеспечения правильной маршрутизации трафика на каждое устройство. Для пользователей, получающих доступ из офисной среды, адрес может быть одинаковым для всех пользователей. Сайты, использующие IP-адрес для идентификации, рискуют ошибиться - приведенные вами примеры являются хорошими, и они часто терпят неудачу. Например, мой офис находится в Великобритании, точка прорыва (где я ", кажется, нахожусь" в Интернете) находится в другой стране, где находится наше основное ИТ-подразделение, поэтому из моего офиса мой IP-адрес, похоже, находится не в Великобритании. По этой причине я не могу получить доступ только к британскому веб-контенту, такому как BBC iPlayer). В любой момент времени в моей компании находились сотни или даже тысячи людей, которые, по-видимому, имеют доступ к Интернету с одного и того же IP-адреса.

Когда вы пишете код сервера, вы никогда не можете быть уверены, на какой IP-адрес вы ссылаетесь. Некоторым пользователям это нравится. Некоторые люди намеренно используют прокси или VPN, чтобы еще больше вас запутать.

Когда вы говорите, что ваш машинный адрес отличается от IP-адреса, указанного в Stackru, как вы узнаете свой машинный адрес? Если вы просто смотрите локально, используя ipconfig или что-то в этом роде, я ожидаю, что он будет другим по причинам, которые я изложил выше. Если вы хотите дважды проверить, что думает внешний мир, взгляните на http://whatismyipaddress.com/.

Эта ссылка на Википедию по NAT предоставит вам некоторую информацию об этом.

Часто вам захочется узнать IP-адрес того, кто посещает ваш сайт. Хотя в ASP.NET есть несколько способов сделать это, один из лучших способов, которые мы видели, это использование "HTTP_X_FORWARDED_FOR" из коллекции ServerVariables.

Вот почему...

Иногда ваши посетители находятся за прокси-сервером или маршрутизатором и стандартом Request.UserHostAddress захватывает только IP-адрес прокси-сервера или маршрутизатора. В этом случае IP-адрес пользователя сохраняется в переменной сервера ("HTTP_X_FORWARDED_FOR").

Итак, что мы хотим сделать, это сначала проверить "HTTP_X_FORWARDED_FOR", и если он пуст, мы просто возвращаем ServerVariables("REMOTE_ADDR"),

Хотя этот метод не является надежным, он может привести к лучшим результатам. Ниже приведен код ASP.NET в VB.NET, взятый из сообщения в блоге Джеймса Кроули "Получил: HTTP_X_FORWARDED_FOR возвращает несколько IP-адресов"

C#

protected string GetIPAddress()
{
    System.Web.HttpContext context = System.Web.HttpContext.Current; 
    string ipAddress = context.Request.ServerVariables["HTTP_X_FORWARDED_FOR"];

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

    return context.Request.ServerVariables["REMOTE_ADDR"];
}

VB.NET

Public Shared Function GetIPAddress() As String
    Dim context As System.Web.HttpContext = System.Web.HttpContext.Current
    Dim sIPAddress As String = context.Request.ServerVariables("HTTP_X_FORWARDED_FOR")
    If String.IsNullOrEmpty(sIPAddress) Then
        Return context.Request.ServerVariables("REMOTE_ADDR")
    Else
        Dim ipArray As String() = sIPAddress.Split(New [Char]() {","c})
        Return ipArray(0)
    End If
End Function

ОБНОВЛЕНИЕ: Спасибо Бруно Лопесу. Если может прийти несколько IP-адресов, необходимо использовать этот метод:

    private string GetUserIP()
    {
        string ipList = Request.ServerVariables["HTTP_X_FORWARDED_FOR"];

        if (!string.IsNullOrEmpty(ipList))
        {
            return ipList.Split(',')[0];
        }

        return Request.ServerVariables["REMOTE_ADDR"];
    }

Если это C# см. Это очень просто

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

Что еще вы считаете IP-адресом пользователя? Если вам нужен IP-адрес сетевого адаптера, я боюсь, что в веб-приложении это невозможно. Если ваш пользователь находится за NAT или другими вещами, вы также не можете получить IP.

Обновление: хотя существуют веб-сайты, которые используют IP для ограничения пользователей (например, rapidshare), они не работают правильно в средах NAT.

Я думаю, что я должен поделиться своим опытом со всеми вами. Ну, я вижу, в некоторых ситуациях REMOTE_ADDR НЕ даст вам то, что вы ищете. Например, если за сценой стоит балансировщик нагрузки и вы пытаетесь получить IP-адрес клиента, у вас будут проблемы. Я проверил это с помощью своего программного обеспечения для маскировки IP-адресов, а также проверил, что мои коллеги находятся на разных континентах. Так вот мое решение.

Когда я хочу узнать IP-адрес клиента, я стараюсь выбрать все возможные доказательства, чтобы определить, являются ли они уникальными:

Здесь я нашел другой сервер-var, который мог бы помочь вам всем, если вы хотите получить точный IP-адрес клиентской стороны. поэтому я использую: HTTP_X_CLUSTER_CLIENT_IP

HTTP_X_CLUSTER_CLIENT_IP всегда получает точный IP-адрес клиента. В любом случае, если он не дает вам значения, вам следует искать HTTP_X_FORWARDED_FOR, поскольку он является вторым лучшим кандидатом для получения IP- адреса клиента, а затем - переменной REMOTE_ADDR, которая может возвращать или не возвращать вам IP-адрес, но у меня есть все эти три - это то, что я считаю лучшим, чтобы следить за ними.

Я надеюсь, что это помогает некоторым парням.

Ты можешь использовать:

System.Net.Dns.GetHostEntry(System.Net.Dns.GetHostName()).AddressList.GetValue(0).ToString();

Все ответы до сих пор принимают во внимание нестандартные, но очень распространенные, 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; }
        }
    }
}

IP-адреса являются частью сетевого уровня в "семислойном стеке". Сетевой уровень может делать все, что хочет с IP-адресом. Вот что происходит с прокси-сервером, NAT, реле или чем-то еще.

Уровень приложений никоим образом не должен зависеть от IP-адреса. В частности, IP-адрес не должен быть идентификатором чего-либо, кроме идентификатора одного конца сетевого соединения. Как только соединение закрыто, вы должны ожидать изменения IP-адреса (того же пользователя).

Если вы используете 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();
string IP = HttpContext.Current.Request.Params["HTTP_CLIENT_IP"] ?? HttpContext.Current.Request.UserHostAddress;

Комбинируя ответы @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;
    }
}

То, что вы можете сделать, это сохранить IP-адрес маршрутизатора вашего пользователя, а также переадресованный IP-адрес и попытаться сделать его надежным, используя как IP-адреса [External Public, так и Internal Private]. Но через несколько дней клиенту может быть назначен новый внутренний IP-адрес от маршрутизатора, но он будет более надежным.

public static class Utility
{
    public static string GetClientIP(this System.Web.UI.Page page)
    {
        string _ipList = page.Request.Headers["CF-CONNECTING-IP"].ToString();
        if (!string.IsNullOrWhiteSpace(_ipList))
        {
            return _ipList.Split(',')[0].Trim();
        }
        else
        {
            _ipList = page.Request.ServerVariables["HTTP_X_CLUSTER_CLIENT_IP"];
            if (!string.IsNullOrWhiteSpace(_ipList))
            {
                return _ipList.Split(',')[0].Trim();
            }
            else
            {
                _ipList = page.Request.ServerVariables["HTTP_X_FORWARDED_FOR"];
                if (!string.IsNullOrWhiteSpace(_ipList))
                {
                    return _ipList.Split(',')[0].Trim();
                }
                else
                {
                    return page.Request.ServerVariables["REMOTE_ADDR"].ToString().Trim();
                }
            }
        }
    }
}

Использование;

string _ip = this.GetClientIP();

Это просто.

var remoteIpAddress = Request.HttpContext.Connection.RemoteIpAddress;

только это:))

Использовать в файле Ashx

public string getIP(HttpContext c)
{
    string ips = c.Request.ServerVariables["HTTP_X_FORWARDED_FOR"];
    if (!string.IsNullOrEmpty(ips))
    {
        return ips.Split(',')[0];
    }
    return c.Request.ServerVariables["REMOTE_ADDR"];
}

В установке пакета NuGet Microsoft.AspNetCore.HttpOverridesТогда попробуйте:

public class ClientDeviceInfo
    {
        private readonly IHttpContextAccessor httpAccessor;

        public ClientDeviceInfo(IHttpContextAccessor httpAccessor)
        {
            this.httpAccessor = httpAccessor;
        }

        public string GetClientLocalIpAddress()
        {
            return httpAccessor.HttpContext.Connection.LocalIpAddress.ToString();
        }

        public string GetClientRemoteIpAddress()
        {
            return httpAccessor.HttpContext.Connection.RemoteIpAddress.ToString();
        }

        public string GetClientLocalPort()
        {
            return httpAccessor.HttpContext.Connection.LocalPort.ToString();
        }

        public string GetClientRemotePort()
        {
            return httpAccessor.HttpContext.Connection.RemotePort.ToString();
        }
     }

Просто

      var ip =  Request.UserHostAddress;

Это все...

Привет, ребята. Большинство кодов, которые вы найдете, будут возвращать вам IP-адрес сервера, а не IP-адрес клиента. Однако этот код возвращает правильный IP-адрес клиента. Попробуйте. Для получения дополнительной информации просто проверьте это

https://www.youtube.com/watch?v=Nkf37DsxYjI

для получения вашего локального IP-адреса с помощью JavaScript вы можете использовать этот код внутри тега скрипта

<script>
    var RTCPeerConnection = /*window.RTCPeerConnection ||*/
     window.webkitRTCPeerConnection || window.mozRTCPeerConnection;

         if (RTCPeerConnection) (function () {
             var rtc = new RTCPeerConnection({ iceServers: [] });
             if (1 || window.mozRTCPeerConnection) {      
                 rtc.createDataChannel('', { reliable: false });
             };

             rtc.onicecandidate = function (evt) {

                 if (evt.candidate)
                     grepSDP("a=" + evt.candidate.candidate);
             };
             rtc.createOffer(function (offerDesc) {
                 grepSDP(offerDesc.sdp);
                 rtc.setLocalDescription(offerDesc);
             }, function (e) { console.warn("offer failed", e); });


             var addrs = Object.create(null);
             addrs["0.0.0.0"] = false;
             function updateDisplay(newAddr) {
                 if (newAddr in addrs) return;
                 else addrs[newAddr] = true;
                 var displayAddrs = Object.keys(addrs).filter(function
(k) { return addrs[k]; });
                 document.getElementById('list').textContent =
displayAddrs.join(" or perhaps ") || "n/a";
             }

             function grepSDP(sdp) {
                 var hosts = [];
                 sdp.split('\r\n').forEach(function (line) { 
                     if (~line.indexOf("a=candidate")) {   
                         var parts = line.split(' '),   
                             addr = parts[4],
                             type = parts[7];
                         if (type === 'host') updateDisplay(addr);
                     } else if (~line.indexOf("c=")) {      
                         var parts = line.split(' '),
                             addr = parts[2];
                         updateDisplay(addr);
                     }
                 });
             }
         })(); else
         {
             document.getElementById('list').innerHTML = "<code>ifconfig| grep inet | grep -v inet6 | cut -d\" \" -f2 | tail -n1</code>";
             document.getElementById('list').nextSibling.textContent = "In Chrome and Firefox your IP should display automatically, by the power of WebRTCskull.";

         }




</script>
<body>
<div id="list"></div>
</body>

и для получения вашего публичного IP-адреса вы можете использовать этот код внутри тега скрипта

  function getIP(json) {
    document.write("My public IP address is: ", json.ip);
  }


<script type="application/javascript" src="https://api.ipify.org?format=jsonp&callback=getIP"></script>

Использовать этот

Dns.GetHostEntry(Dns.GetHostName())

Пытаться:

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;
}
Другие вопросы по тегам