ASP.NET에는 속성 값 의 IP 주소를 제공 할 수있는 속성이 System.Web.HttpRequest
포함 된 클래스가 있습니다 .ServerVariables
REMOTE_ADDR
그러나 ASP.NET Web API에서 원격 호스트의 IP 주소를 얻는 비슷한 방법을 찾을 수 없습니다.
요청하는 원격 호스트의 IP 주소를 어떻게 얻을 수 있습니까?
답변
그렇게 할 수는 있지만 검색 할 수는 없습니다. 들어오는 요청에서 속성 백을 사용해야하며 액세스 해야하는 속성은 IIS에서 웹 API를 사용하는지 (웹 호스팅) 또는 자체 호스팅인지에 따라 다릅니다. 아래 코드는이 작업을 수행하는 방법을 보여줍니다.
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;
}
답변
이 솔루션은 또한 Owin을 사용하여 자체 호스팅 된 웹 API를 다룹니다. 여기 에서 부분적으로 .
ApiController
웹 API를 호스팅하는 방법에 관계없이 원격 IP 주소를 반환 하는 개인용 메소드를 작성할 수 있습니다 .
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.dllRemoteEndpointMessageProperty
-System.ServiceModel.dllOwinContext
-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();
}
}
답변
실제로 하나의 라이너를 원하고 웹 API를 자체 호스팅하지 않으려는 경우 :
((System.Web.HttpContextWrapper)Request.Properties["MS_HttpContext"]).Request.UserHostAddress;
답변
위의 답변에는 속성을 HttpContext 또는 HttpContextWrapper로 캐스팅하려면 System.Web에 대한 참조가 필요합니다. 참조를 원하지 않으면 동적을 사용하여 ip를 얻을 수 있습니다.
var host = ((dynamic)request.Properties["MS_HttpContext"]).Request.UserHostAddress;
답변
carlosfigueira가 제공하는 솔루션은 효과가 있지만, 유형이 안전한 원 라이너가 더 좋습니다. 액션 방법에 using System.Web
액세스 권한 HttpContext.Current.Request.UserHostAddress
을 추가하십시오 .