Получить IP-адрес удаленного хоста
В ASP.NET существует класс System.Web.HttpRequest
, который содержит свойство ServerVariables
, которое может предоставить нам IP-адрес из значения свойства REMOTE_ADDR
.
Однако я не смог найти аналогичный способ получить IP-адрес удаленного хоста из веб-API ASP.NET.
Как я могу получить IP-адрес удаленного хоста, делающего запрос?
Ответы
Ответ 1
Это можно сделать, но не очень легко обнаружить - вам нужно использовать пакет свойств из входящего запроса, а свойство, которое вам нужно получить, зависит от того, используете ли вы веб-API в IIS (веб-хостинг) или самостоятельно -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;
}
Ответ 2
Это решение также охватывает веб-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();
}
}
Ответ 3
Если вы действительно хотите однострочный интерфейс и не планируете самостоятельный веб-API:
((System.Web.HttpContextWrapper)Request.Properties["MS_HttpContext"]).Request.UserHostAddress;
Ответ 4
В ответах требуется ссылка на System.Web, чтобы иметь возможность передать свойство HttpContext или HttpContextWrapper. Если вам не нужна ссылка, вы можете получить ip с помощью динамического:
var host = ((dynamic)request.Properties["MS_HttpContext"]).Request.UserHostAddress;
Ответ 5
Решение, предоставляемое carlosfigueira, работает, но безопасные однострочные шрифты лучше: добавьте using System.Web
, затем войдите в HttpContext.Current.Request.UserHostAddress
в свой метод действий.