web-dev-qa-db-fra.com

Comment obtenir l'adresse IP du client d'un utilisateur dans ASP.NET?

Nous avons Request.UserHostAddress pour obtenir l'adresse IP dans ASP.NET, mais il s'agit généralement de l'adresse IP du fournisseur d'accès à Internet, pas exactement de l'adresse IP de la machine de l'utilisateur qui, par exemple, a cliqué sur un lien. Comment puis-je obtenir la vraie adresse IP?

Par exemple, dans un profil utilisateur Stack Overflow, il s'agit de: "Dernière activité du compte: il y a 4 heures de 86.123.127.8" , mais l'adresse IP de mon ordinateur est légèrement différente. Comment Stack Overflow obtient-il cette adresse? 

Dans certains systèmes Web, il existe une vérification d’adresse IP à certaines fins. Par exemple, avec une certaine adresse IP, l'utilisateur ne peut-il avoir que 5 clics sur les liens de téléchargement toutes les 24 heures? Cette adresse IP doit être unique, pas pour un fournisseur de services Internet qui compte un très grand nombre de clients ou d'utilisateurs Internet.

Ai-je bien compris?

350
mahdiahmadirad

Comme d'autres l'ont dit, vous ne pouvez pas faire ce que vous demandez. Si vous décrivez le problème que vous essayez de résoudre, peut-être que quelqu'un pourra vous aider? Par exemple. essayez-vous d'identifier de manière unique vos utilisateurs? Pourriez-vous utiliser un cookie ou l'ID de session peut-être à la place de l'adresse IP?

Edit L'adresse que vous voyez sur le serveur ne doit pas être celle du FAI, car vous dites que ce serait une plage énorme. L’adresse d’un utilisateur domestique en bande large sera l’adresse de son routeur. Ainsi, chaque périphérique de la maison semblera identique à l’extérieur, mais le routeur utilise NAT pour s’assurer que le trafic est acheminé vers chaque périphérique. correctement. Pour les utilisateurs accédant depuis un environnement de bureau, l'adresse peut être identique pour tous les utilisateurs. Les sites qui utilisent une adresse IP comme identifiant risquent fort de se tromper. Les exemples que vous donnez sont de bons exemples et ils échouent souvent. Par exemple, mon bureau se trouve au Royaume-Uni, le point de rupture (où «il semble que» se trouve sur Internet) se trouve dans un autre pays où se trouve notre centre informatique principal. Mon adresse IP ne semble donc pas se trouver au Royaume-Uni. Pour cette raison, je ne peux pas accéder au contenu Web britannique uniquement, tel que le BBC iPlayer). À tout moment, des centaines, voire des milliers de personnes de mon entreprise semblent accéder au Web à partir de la même adresse IP.

Lorsque vous écrivez du code serveur, vous ne pouvez jamais être sûr de l'adresse IP que vous voyez. Certains utilisateurs l'aiment de cette façon. Certaines personnes utilisent délibérément un proxy ou un VPN pour vous décontenancer davantage.

Quand vous dites que l'adresse de votre machine est différente de l'adresse IP indiquée sur StackOverflow, comment trouvez-vous l'adresse de votre machine? Si vous regardez juste localement en utilisant ipconfig ou quelque chose du genre, je m'attendrais à ce que ce soit différent pour les raisons que j'ai exposées ci-dessus. Si vous voulez vérifier ce que le monde extérieur pense, jetez un œil à whatismyipaddress.com/ .

Ce lien Wikipedia sur NAT vous fournira des informations de base à ce sujet.

131
Steve Haigh

Vous voudrez souvent connaître l'adresse IP d'une personne visitant votre site Web. Bien qu'ASP.NET propose plusieurs méthodes pour cela, l'une des meilleures que nous ayons vu consiste à utiliser "HTTP_X_FORWARDED_FOR" de la collection ServerVariables.

Voici pourquoi...

Parfois, vos visiteurs sont derrière un serveur proxy ou un routeur et le Request.UserHostAddress standard ne capture que l'adresse IP du serveur proxy ou du routeur. Dans ce cas, l'adresse IP de l'utilisateur est ensuite stockée dans la variable serveur ("HTTP_X_FORWARDED_FOR").

Donc, ce que nous voulons faire, c'est d'abord vérifier "HTTP_X_FORWARDED_FOR" et si cela est vide, alors nous retournons simplement ServerVariables("REMOTE_ADDR").

Bien que cette méthode ne soit pas infaillible, elle peut conduire à de meilleurs résultats. Ci-dessous, le code ASP.NET dans VB.NET, extrait de Le blog de James Crowley "Gotcha: HTTP_X_FORWARDED_FOR renvoie plusieurs adresses 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
405
mangokun

MISE À JOUR: .__ Merci à Bruno Lopes. Si plusieurs adresses IP peuvent venir alors besoin d'utiliser cette méthode:

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

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

        return Request.ServerVariables["REMOTE_ADDR"];
    }
70
algreat

Que considérez-vous de plus l'adresse IP de l'utilisateur? Si vous souhaitez connaître l'adresse IP de la carte réseau, je crains fort qu'il ne soit pas possible de le faire dans une application Web. Si votre utilisateur est derrière NAT ou d’autres éléments, vous ne pouvez pas obtenir l’adresse IP non plus.

Update : Bien que certains sites Web utilisent IP pour limiter l'utilisateur (comme rapidshare), ils ne fonctionnent pas correctement dans les environnements NAT.

23
Mehrdad Afshari

Si c # voit de cette façon, c'est très simple

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

Je pense que je devrais partager mon expérience avec vous tous. Eh bien, je vois que dans certaines situations REMOTE_ADDR ne vous obtiendra PAS ce que vous recherchez. Par exemple, si vous avez un équilibreur de charge dans les coulisses et si vous essayez d'obtenir l'adresse IP du client, vous aurez des problèmes. Je l'ai vérifié avec mon logiciel de masquage IP et j'ai également vérifié auprès de mes collègues qui se trouvaient sur différents continents. Alors voici ma solution.

Lorsque je veux connaître l'adresse IP d'un client, j'essaie de sélectionner toutes les preuves possibles afin de déterminer si elles sont uniques:

Ici, j'ai trouvé une autre variable sever-var qui pourrait vous aider si vous voulez obtenir une adresse IP exacte du côté client. donc j'utilise: HTTP_X_CLUSTER_CLIENT_IP

HTTP_X_CLUSTER_CLIENT_IP obtient toujours l'adresse IP exacte du client. Dans tous les cas, si cela ne vous donne pas la valeur, vous devriez alors rechercher HTTP_X_FORWARDED_FOR car c’est le deuxième meilleur candidat pour obtenir l’IP du client, puis le REMOTE_ADDR var qui peut vous renvoyer ou non. IP, mais pour moi, avoir tous ces trois est ce que je trouve la meilleure chose pour les surveiller.

J'espère que cela aide certains gars. 

21
KMX

Vous pouvez utiliser:

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

Les adresses IP font partie de la couche réseau dans la "pile à sept couches". La couche réseau peut faire ce qu’elle veut avec l’adresse IP. C'est ce qui se passe avec un serveur proxy, NAT, relais, ou autre chose.

La couche d'application ne doit en aucun cas dépendre de l'adresse IP. En particulier, une adresse IP n’est pas censée être un identificateur autre que l’identificateur de l’une des extrémités d’une connexion réseau. Dès qu'une connexion est fermée, vous devez vous attendre à ce que l'adresse IP (du même utilisateur) change.

14
John Saunders

Si vous utilisez CloudFlare, vous pouvez essayer cette Méthode d'extension :

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;
    }
}

puis

string IPAddress = Request.GetIPAddress();
9
Tony
string IP = HttpContext.Current.Request.Params["HTTP_CLIENT_IP"] ?? HttpContext.Current.Request.UserHostAddress;
8
GorkemHalulu

Jusqu'à présent, toutes les réponses prennent en compte l'en-tête non standard, mais très commun, X-Forwarded-For. Il existe un en-tête normalisé Forwarded qui est un peu plus difficile à analyser. Quelques exemples sont les suivants:

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

J'ai écrit un cours qui prend en compte ces deux en-têtes lors de la détermination de l'adresse IP d'un client.

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;
        }
    }
}

Voici quelques tests unitaires que j'ai utilisés pour valider ma solution:

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; }
        }
    }
}
7
dana

Ce que vous pouvez faire est de stocker l'adresse IP du routeur de votre utilisateur ainsi que l'adresse IP transférée et d'essayer de la rendre fiable en utilisant les adresses IP [externe public et interne privé]. Mais de nouveau, après quelques jours, une nouvelle adresse IP interne du routeur peut être attribuée au client, mais celle-ci sera plus fiable. 

7
Shahid

En combinant les réponses de @Tony et @mangokun , j'ai créé la méthode d'extension suivante:

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;
    }
}
4
Nitesh

utiliser dans un fichier 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"];
}
3
Behnam Mohammadi

Bonjour les gars La plupart des codes que vous trouverez vous renverront l'adresse IP de votre serveur, pas l'adresse IP du client.

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

pour obtenir votre adresse IP locale en utilisant javascript, vous pouvez utiliser Mettez ce code dans votre balise script

<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>

et pour obtenir votre adresse IP publique, vous pouvez utiliser mettre ce code dans votre balise script

  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>
0
Shubham