[C#] 원격 호스트의 IP 주소를 얻습니다

ASP.NET에는 속성 값 의 IP 주소를 제공 할 수있는 속성이 System.Web.HttpRequest포함 된 클래스가 있습니다 .ServerVariablesREMOTE_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.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();
    }
}


답변

실제로 하나의 라이너를 원하고 웹 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을 추가하십시오 .


답변