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

206

Подскажите пожалуйста, как мне получить IP-адрес клиента в ASP.NET при использовании MVC 6. Request.ServerVariables["REMOTE_ADDR"]Не работает.

eadam
источник
Пример:httpContext.GetFeature<IHttpConnectionFeature>().RemoteIpAddress
Киран Чалла
Причина задержки указана в нижней части вопроса: «Существует слишком много возможных ответов, или хорошие ответы будут слишком длинными для этого формата. Пожалуйста, добавьте детали, чтобы сузить набор ответов или выделить проблему, на которую можно ответить в». несколько абзацев ".
Кевин Браун
12
Я не думаю, что ответ достаточно длинный. Это простая вещь, которую мы делаем в старых версиях MVC. Я просто спросил, как это сделать в последней бета-версии. Во-вторых, если есть много ответов, почему бы никому просто не указать мне на ОДИН из них. Infact, MVC 6 - бета, и я думаю, что они даже не прочитали вопрос должным образом прежде, чем держать это.
Eadam
Отредактируйте свой вопрос, показывая больше того, что вы пробовали, и понятный ввод / вывод. не жалуйтесь, что ваш вопрос закрыт, по крайней мере, не пытаясь улучшить его.
10
Только программисты из одного домена должны закрыть вопрос. Любой, кто работает в asp.net 5.0, просто знает, что я спрашиваю, за доли секунды. Остальные просто наказывают меня за публикацию простого вопроса.
eadam

Ответы:

276

API был обновлен. Не уверен, когда это изменилось, но, по словам Дэмиена Эдвардса в конце декабря, теперь вы можете сделать это:

var remoteIpAddress = request.HttpContext.Connection.RemoteIpAddress;
Дэвид Педен
источник
9
Это RemoteIpAddressвсегда nullдля меня, когда я публикую его веб-сайт на IIS и регистрирую это в файле.
A-Sharabiani
3
Похоже, что проблема была исправлена ​​в RC 2
Jon
13
Я всегда получаю 127.0.0.1, даже когда подключаюсь удаленно
морозно
33
Это возвращает «:: 1» для меня, который является форматом IPv6. Как другие видят 127.0.0.1?
Дерек Грир
4
Кто-нибудь еще возвращает локальный IP-адрес своего IIS-сервера?
dave317
73

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

Некоторые полезные ссылки: Как получить IP-адрес клиента в ASP.NET CORE? и RemoteIpAddress всегда равен нулю

Это ::1может быть из-за:

Завершение соединений в IIS, который затем перенаправляется на Kestrel, веб-сервер v.next, поэтому соединения с веб-сервером действительно выполняются с localhost. ( https://stackoverflow.com/a/35442401/5326387 )

JohnÂ?
источник
6
Это правильный ответ, который также задокументирован в официальной документации об обратных прокси- серверах
Melvyn
8
необходимо указать, что "app.UseForwardedHeaders ..." необходимо добавить перед app.UseAuthentication (); линия, в случае если вы используете идентификацию
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.

crokusek
источник
2
Это правильный ответ. Не существует единственного способа получить IP-адрес, особенно когда ваше приложение находится за Nginx, балансировщиком нагрузки или чем-то в этом роде. Спасибо!
Feu
@feu вроде, поскольку AspNetCore может переопределять свойство RemoteIpAddress с помощью заголовков, таких как X-Forwarded-For.
Марк Лопес
@crokusek ... пытаюсь адаптировать ваше решение, но VS вынуждает меня к классу инкапсуляции этого кода static. У вас есть этот код в вашем проекте веб-приложения или в библиотеке классов в решении?
dinotom
Первые 2 метода должны быть в экземпляре, который предоставляет __httpContextAccessor (или адаптирует его). Вторые 2 строковых метода были взяты из отдельного класса статических расширений.
crokusek
Это хорошее решение, особенно когда ваше приложение использует Kestrel и размещается с Nginx в Linux.
Тимоти Мачария
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/…IHttpConnectionFeature не поддерживается в Kestrel (пока).
Qbik
@JerryBian это сейчас
Дэвид Педен
Должно быть устаревшим - @feradz версия работает для меня в RC-1
приказном
12
var remoteIpAddress = HttpContext.Features.Get<IHttpConnectionFeature>()?.RemoteIpAddress;
feradz
источник
6
Слишком сложно. MVC уже называет это внутренне и помещает это под HttpContext.Connection.RemoteIpAddress.
Фред
@Fred - ваша версия возвращает мне ноль в RC-1 - IIS и Kestrel
указ
7

Это работает для меня (DotNetCore 2.1)

[HttpGet]
public string Get() 
{
    var remoteIpAddress = HttpContext.Connection.RemoteIpAddress;
    return remoteIpAddress.ToString();
}
MC9000
источник
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()

Вот как это делается.

hojjat.mi
источник
2
Это дает мне :: 1. Asp.Net Core 2.2., На локальном хосте.
Stian
::1это локальный хост в IPv6. Эквивалент IPv4127.0.0.1
Энди
3

В моем случае у меня есть приложение DotNet Core 2.2 Web, работающее на DigitalOcean с докером и 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();
gorums
источник
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

получить IP-адрес и имя хоста в ядре .net

поместите этот код в контроллер

Следуй этим шагам:

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. чтобы получить IP-адрес, используйте этот код в любом из ваших 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();
    }

и теперь вы можете получить IPv4-адрес из remoteIpAddress или результат

Sruit A.Suk
источник
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

При запуске ASP.NET Core 2.1 за обратным прокси-сервером Traefik в Ubuntu, мне нужно установить IP-адрес шлюза KnownProxiesпосле установки официального Microsoft.AspNetCore.HttpOverridesпакета

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

Согласно документации , это требуется, если обратный прокси-сервер не работает на localhost. docker-compose.ymlИз Traefik назначил статический IP - адрес:

networks:
  my-docker-network:
    ipv4_address: 192.168.3.2

В качестве альтернативы, этого должно быть достаточно, чтобы убедиться, что здесь определена известная сеть, чтобы указать ее шлюз в .NET Core.

лев
источник