Comment obtenir l'adresse IP du client dans ASP.NET CORE?

202

Pouvez-vous s'il vous plaît laissez-moi savoir comment obtenir l'adresse IP du client dans ASP.NET lorsque l'utilisation de MVC 6. Request.ServerVariables["REMOTE_ADDR"]ne fonctionne pas.

eadam
la source
Exemple:httpContext.GetFeature<IHttpConnectionFeature>().RemoteIpAddress
Kiran Challa
La raison de la suspension est disponible au bas de la question: "Il y a trop de réponses possibles, ou les bonnes réponses seraient trop longues pour ce format. Veuillez ajouter des détails pour affiner l'ensemble de réponses ou pour isoler un problème auquel il est possible de répondre dans quelques paragraphes. "
Kevin Brown
12
Je ne pense pas que la réponse soit suffisamment longue. C'est une chose simple que nous faisons dans les anciennes versions de MVC. Je viens de demander comment le faire dans la dernière version bêta. Deuxièmement, s'il y a beaucoup de réponses, pourquoi personne ne me pointe-t-il vers UNE d'entre elles? En fait, MVC 6 est une version bêta et je pense qu'ils n'ont même pas lu la question correctement avant de la tenir.
eadam
Modifiez votre question en montrant plus de ce que vous avez essayé et une entrée / sortie claire. ne vous plaignez pas seulement que votre question a été close sans au moins essayer de l'améliorer.
10
Seuls les programmeurs du même domaine doivent fermer la question. Quiconque travaille sur asp.net 5.0 saura simplement ce que je demande en une fraction de seconde. Le reste d'entre vous me punit simplement pour avoir posté une simple question.
eadam

Réponses:

271

L'API a été mise à jour. Je ne sais pas quand cela a changé, mais selon Damien Edwards fin décembre, vous pouvez maintenant le faire:

var remoteIpAddress = request.HttpContext.Connection.RemoteIpAddress;
David Peden
la source
9
C'est RemoteIpAddresstoujours nullpour moi, lorsque je publie le site Web sur IIS et que je l'enregistre dans un fichier.
A-Sharabiani
3
On dirait que le problème a été corrigé dans rc 2
Jon
12
Je reçois toujours 127.0.0.1 même lorsque je me connecte à distance
Frostymarvelous
32
Cela renvoie pour moi ":: 1" qui est le format IPv6. Comment les autres voient-ils 127.0.0.1?
Derek Greer
4
Quelqu'un d'autre obtient-il l'adresse IP locale de son serveur IIS?
dave317
73

Dans project.json, ajoutez une dépendance à:

"Microsoft.AspNetCore.HttpOverrides": "1.0.0"

Dans Startup.cs, dans la Configure()méthode, ajoutez:

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

Et bien sûr:

using Microsoft.AspNetCore.HttpOverrides;

Ensuite, je pouvais obtenir l'ip en utilisant:

Request.HttpContext.Connection.RemoteIpAddress

Dans mon cas, lors du débogage dans VS, j'ai toujours obtenu l'hôte local IpV6, mais lors du déploiement sur un IIS, j'ai toujours eu l'IP distante.

Quelques liens utiles: Comment obtenir l'adresse IP du client dans ASP.NET CORE? et RemoteIpAddress est toujours null

C'est ::1peut-être à cause de:

Terminaison des connexions à IIS, qui transmet ensuite à Kestrel, le serveur Web v.next, de sorte que les connexions au serveur Web proviennent en effet de localhost. ( https://stackoverflow.com/a/35442401/5326387 )

Johna
la source
6
C'est la bonne réponse, qui est également documentée dans la documentation officielle sur les proxys inversés: docs.microsoft.com/en-us/aspnet/core/host-and-deploy/…
Melvyn
8
besoin de souligner que le "app.UseForwardedHeaders ..." doit être ajouté avant le app.UseAuthentication (); ligne, dans le cas où vous utilisez l'indentation
netfed
1
Cela a parfaitement fonctionné et j'ai testé sur IIS hébergé localement et sur Azure. Fonctionne aux deux endroits.
ThomasCle
72

Une logique de secours peut être ajoutée pour gérer la présence d'un équilibreur de charge.

De plus, grâce à l'inspection, l'en- X-Forwarded-Fortête est de toute façon défini même sans Load Balancer (peut-être à cause d'une couche Kestrel supplémentaire?):

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

Suppose que l'ID a _httpContextAccessorété fourni.

crokusek
la source
2
CECI est la bonne réponse. Il n'y a pas une seule façon de récupérer l'adresse IP, surtout lorsque votre application est derrière un Nginx, un équilibreur de charge ou quelque chose comme ça. Merci!
Feu
@feu, car AspNetCore peut remplacer la propriété RemoteIpAddress avec des en-têtes comme X-Forwarded-For.
Mark Lopez
@crokusek ... essayant d'adapter votre solution, mais VS me forçant à la classe encapsulant ce code statique. Avez-vous ce code dans votre projet d'application Web ou dans une bibliothèque de classes dans la solution?
dinotom
Les 2 premières méthodes doivent être dans une instance qui fournit __httpContextAccessor (ou l'adapter). Les deux autres méthodes de chaîne ont été extraites d'une classe d'extensions statiques distincte.
crokusek
C'est une bonne solution, surtout lorsque votre application utilise Kestrel et est hébergée avec Nginx sur Linux.
Timothy Macharia
16

Vous pouvez utiliser le IHttpConnectionFeaturepour obtenir ces informations.

var remoteIpAddress = httpContext.GetFeature<IHttpConnectionFeature>()?.RemoteIpAddress;
Kiran Challa
la source
Merci d'avoir répondu!
eadam
2
Cela fonctionne-t-il pour l'hébergement Kestrel? Dans ma démo, httpContext.GetFeature<IHttpConnectionFeature>()soyez toujours null.
Jerry Bian
2
@JerryBian selon ce document: github.com/aspnet/Docs/blob/master/aspnet/fundamentals/… , IHttpConnectionFeature n'est pas encore pris en charge dans Kestrel.
qbik
@JerryBian c'est maintenant
David Peden
Doit être obsolète - la version @feradz fonctionne pour moi dans RC-1
fiat
12
var remoteIpAddress = HttpContext.Features.Get<IHttpConnectionFeature>()?.RemoteIpAddress;
feradz
la source
6
Trop compliqué. MVC appelle déjà cela en interne et le soumet HttpContext.Connection.RemoteIpAddress.
Fred
@Fred - votre version retourne nulle pour moi dans RC-1 - IIS et Kestrel
fiat
7

Dans ASP.NET 2.1, dans StartUp.cs, ajoutez ces services:

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

puis faites 3 étapes:

  1. Définissez une variable dans votre contrôleur MVC

    private IHttpContextAccessor _accessor;
  2. DI dans le constructeur du contrôleur

    public SomeController(IHttpContextAccessor accessor)
    {
        _accessor = accessor;
    }
  3. Récupérer l'adresse IP

    _accessor.HttpContext.Connection.RemoteIpAddress.ToString()

Voilà comment cela se fait.

hojjat.mi
la source
2
Cela me donne :: 1. Asp.Net Core 2.2., Sur localhost.
Stian
::1est localhost dans IPv6. L'équivalent IPv4 de127.0.0.1
Andy
6

Cela fonctionne pour moi (DotNetCore 2.1)

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

Dans mon cas, j'ai l'application Web DotNet Core 2.2 exécutée sur DigitalOcean avec docker et nginx comme proxy inverse. Avec ce code dans Startup.cs, je peux obtenir l'adresse IP du client

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 était l'adresse IP que j'obtenais avant d'utiliser

Request.HttpContext.Connection.RemoteIpAddress.ToString();
gorums
la source
2

Tout d'abord, dans .Net Core 1.0 Ajouter using Microsoft.AspNetCore.Http.Features;au contrôleur Puis à l'intérieur de la méthode appropriée:

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

J'ai lu plusieurs autres réponses qui n'ont pas pu être compilées car elles utilisaient un httpContext en minuscules, ce qui a conduit les VS à ajouter à l'aide de Microsoft.AspNetCore.Http, au lieu de l'utilisation appropriée, ou avec HttpContext (le compilateur est également trompeur).

Gars
la source
2

obtenir l'adresse IP et le nom d'hôte dans le noyau .net

mettre ce code dans le contrôleur

Suivez ces étapes:

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

J'ai trouvé que certains d'entre vous ont trouvé que l'adresse IP que vous obtenez est ::: 1 ou 0.0.0.1

C'est le problème car vous essayez d'obtenir l'IP de votre propre machine et la confusion de C # qui essaie de renvoyer IPv6.

Donc, j'implémente la réponse de @Johna ( https://stackoverflow.com/a/41335701/812720 ) et @David ( https://stackoverflow.com/a/8597351/812720 ), merci à eux!

et ici à la solution:

  1. ajouter le package Microsoft.AspNetCore.HttpOverrides dans vos références (dépendances / packages)

  2. ajoutez cette ligne dans 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. pour obtenir IPAddress, utilisez ce code dans n'importe lequel de vos 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();
    }

et maintenant vous pouvez obtenir l'adresse IPv4 de remoteIpAddress ou du résultat

Sruit A.Suk
la source
1

essaye ça.

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

L'exécution de .NET core(3.1.4) IISderrière un équilibreur de charge ne fonctionnait pas avec d'autres solutions suggérées.

La lecture manuelle de l'en- X-Forwarded-Fortête le fait.

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

J'exécute un package autonome en utilisant le pack d'hébergement .

Aage
la source
0

En exécutant ASP.NET Core 2.1 derrière un proxy inverse Traefik sur Ubuntu, je dois définir son IP de passerelle KnownProxiesaprès avoir installé le Microsoft.AspNetCore.HttpOverridespackage officiel

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

Selon la documentation , cela est nécessaire si le proxy inverse ne fonctionne pas sur localhost. Le docker-compose.ymlde Traefik a attribué une adresse IP statique:

networks:
  my-docker-network:
    ipv4_address: 192.168.3.2

Alternativement, il devrait suffire de s'assurer qu'un réseau connu est défini ici pour spécifier sa passerelle dans .NET Core.

Lion
la source