Получить IP-адрес удаленного хоста - PullRequest
131 голосов
/ 05 марта 2012

В ASP.NET есть класс System.Web.HttpRequest, который содержит свойство ServerVariables, которое может предоставить нам IP-адрес из значения свойства REMOTE_ADDR.

Однако я не смог найти аналогичный способполучить IP-адрес удаленного хоста из ASP.NET Web API.

Как я могу получить IP-адрес удаленного хоста, который делает запрос?

Ответы [ 5 ]

183 голосов
/ 05 марта 2012

Это можно сделать, но не очень легко обнаружить - вам нужно использовать пакет свойств из входящего запроса, а свойство, к которому вам нужно получить доступ, зависит от того, используете ли вы Web API в IIS (webhosted) или самостоятельно-hosted.Код ниже показывает, как это можно сделать.

private string GetClientIp(HttpRequestMessage request)
{
    if (request.Properties.ContainsKey("MS_HttpContext"))
    {
        return ((HttpContextWrapper)request.Properties["MS_HttpContext"]).Request.UserHostAddress;
    }

    if (request.Properties.ContainsKey(RemoteEndpointMessageProperty.Name))
    {
        RemoteEndpointMessageProperty prop;
        prop = (RemoteEndpointMessageProperty)request.Properties[RemoteEndpointMessageProperty.Name];
        return prop.Address;
    }

    return null;
}
73 голосов
/ 08 ноября 2013

Это решение также охватывает веб-API, размещенный самостоятельно с помощью Owin.Частично из здесь .

Вы можете создать в вас приватный метод ApiController, который будет возвращать удаленный IP-адрес независимо от того, как вы размещаете свой веб-API:

 private const string HttpContext = "MS_HttpContext";
 private const string RemoteEndpointMessage =
     "System.ServiceModel.Channels.RemoteEndpointMessageProperty";
 private const string OwinContext = "MS_OwinContext";

 private string GetClientIp(HttpRequestMessage request)
 {
       // Web-hosting
       if (request.Properties.ContainsKey(HttpContext ))
       {
            HttpContextWrapper ctx = 
                (HttpContextWrapper)request.Properties[HttpContext];
            if (ctx != null)
            {
                return ctx.Request.UserHostAddress;
            }
       }

       // Self-hosting
       if (request.Properties.ContainsKey(RemoteEndpointMessage))
       {
            RemoteEndpointMessageProperty remoteEndpoint =
                (RemoteEndpointMessageProperty)request.Properties[RemoteEndpointMessage];
            if (remoteEndpoint != null)
            {
                return remoteEndpoint.Address;
            }
        }

       // Self-hosting using Owin
       if (request.Properties.ContainsKey(OwinContext))
       {
           OwinContext owinContext = (OwinContext)request.Properties[OwinContext];
           if (owinContext != null)
           {
               return owinContext.Request.RemoteIpAddress;
           }
       }

        return null;
 }

Требуются ссылки:

  • HttpContextWrapper - System.Web.dll
  • RemoteEndpointMessageProperty - System.ServiceModel.dll
  • OwinContext - Microsoft.Owin.dll (у вас уже будет, если вы используете пакет Owin)

Небольшая проблема с этим решением состоит в том, что вам нужно загружать библиотеки для всех 3 случаев, когда вы фактически будете использовать только один из нихво время выполнения.Как предлагается здесь , это можно преодолеть с помощью dynamic переменных.Вы также можете написать GetClientIpAddress метод в качестве расширения для HttpRequestMethod.

using System.Net.Http;

public static class HttpRequestMessageExtensions
{
    private const string HttpContext = "MS_HttpContext";
    private const string RemoteEndpointMessage =
        "System.ServiceModel.Channels.RemoteEndpointMessageProperty";
    private const string OwinContext = "MS_OwinContext";

    public static string GetClientIpAddress(this HttpRequestMessage request)
    {
       // Web-hosting. Needs reference to System.Web.dll
       if (request.Properties.ContainsKey(HttpContext))
       {
           dynamic ctx = request.Properties[HttpContext];
           if (ctx != null)
           {
               return ctx.Request.UserHostAddress;
           }
       }

       // Self-hosting. Needs reference to System.ServiceModel.dll. 
       if (request.Properties.ContainsKey(RemoteEndpointMessage))
       {
            dynamic remoteEndpoint = request.Properties[RemoteEndpointMessage];
            if (remoteEndpoint != null)
            {
                return remoteEndpoint.Address;
            }
        }

       // Self-hosting using Owin. Needs reference to Microsoft.Owin.dll. 
       if (request.Properties.ContainsKey(OwinContext))
       {
           dynamic owinContext = request.Properties[OwinContext];
           if (owinContext != null)
           {
               return owinContext.Request.RemoteIpAddress;
           }
       }

        return null;
    }
}

Теперь вы можете использовать его следующим образом:

public class TestController : ApiController
{
    [HttpPost]
    [ActionName("TestRemoteIp")]
    public string TestRemoteIp()
    {
        return Request.GetClientIpAddress();
    }
}
31 голосов
/ 09 августа 2013

Если вы действительно хотите использовать одну строку и не планируете самостоятельно размещать веб-API:

((System.Web.HttpContextWrapper)Request.Properties["MS_HttpContext"]).Request.UserHostAddress;
13 голосов
/ 14 мая 2014

Над ответами требуется ссылка на System.Web, чтобы можно было привести свойство к HttpContext или HttpContextWrapper. Если вы не хотите ссылку, вы можете получить IP с помощью динамического:

var host = ((dynamic)request.Properties["MS_HttpContext"]).Request.UserHostAddress;
0 голосов
/ 12 июня 2012

Решение, предоставленное carlosfigueira, работает, но безопасные однострочники лучше: добавьте using System.Web, затем получите доступ к HttpContext.Current.Request.UserHostAddress в вашем методе действия.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...