【问题标题】:Asp Net Web API 2.1 get client IP addressAsp Net Web API 2.1 获取客户端IP地址
【发布时间】:2014-04-27 06:55:18
【问题描述】:

您好,我需要获取请求 Web api 中某些方法的客户端 IP, 我曾尝试使用来自here 的代码,但它总是返回服务器本地 IP, 如何正确进入?

HttpContext.Current.Request.UserHostAddress;

来自其他问题:

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

        public static string GetClientIpAddress(this HttpRequestMessage request)
        {
            if (request.Properties.ContainsKey(HttpContext))
            {
                dynamic ctx = request.Properties[HttpContext];
                if (ctx != null)
                {
                    return ctx.Request.UserHostAddress;
                }
            }

            if (request.Properties.ContainsKey(RemoteEndpointMessage))
            {
                dynamic remoteEndpoint = request.Properties[RemoteEndpointMessage];
                if (remoteEndpoint != null)
                {
                    return remoteEndpoint.Address;
                }
            }

            return null;
        }
    }

【问题讨论】:

标签: c# asp.net asp.net-web-api


【解决方案1】:

以下链接可能会对您有所帮助。以下是来自以下链接的代码。

参考:getting-the-client-ip-via-asp-net-web-api

using System.Net.Http;
using System.ServiceModel.Channels;
using System.Web;
using System.Web.Http;


namespace Trikks.Controllers.Api
{
    public class IpController : ApiController
    {
          public string GetIp()
          {
                return GetClientIp();
          }

          private string GetClientIp(HttpRequestMessage request = null)
          {
                request = request ?? Request;

                if (request.Properties.ContainsKey("MS_HttpContext"))
                {
                      return   ((HttpContextWrapper)request.Properties["MS_HttpContext"]).Request.UserHostAddress;
                }
                else if (request.Properties.ContainsKey(RemoteEndpointMessageProperty.Name))
                {
                     RemoteEndpointMessageProperty prop = (RemoteEndpointMessageProperty)request.Properties[RemoteEndpointMessageProperty.Name];
                     return prop.Address;
                }
                else if (HttpContext.Current != null)
                {
                    return HttpContext.Current.Request.UserHostAddress;
                }
                else
                {
                      return null;
                }
           }
     }
}

下面是另一种方法。

参考:how-to-access-the-client-s-ip-address

对于网络托管版本

string clientAddress = HttpContext.Current.Request.UserHostAddress;

自托管

object property;
        Request.Properties.TryGetValue(typeof(RemoteEndpointMessageProperty).FullName, out property);
        RemoteEndpointMessageProperty remoteProperty = property as RemoteEndpointMessageProperty;

【讨论】:

    【解决方案2】:

    使用 Web API 2.2:Request.GetOwinContext().Request.RemoteIpAddress

    【讨论】:

    【解决方案3】:

    尝试获取IP使用

    ip = HttpContext.Current != null ? HttpContext.Current.Request.UserHostAddress : "";
    

    【讨论】:

    • @DenisBabarykin 我认为应该,..它返回服务器变量 REMOTE_ADDR 中的 IP 地址
    【解决方案4】:

    如果您使用 OWIN 自托管 NuGet 包通过 Asp.Net 2.1 自托管,则可以使用以下代码:

     private string getClientIp(HttpRequestMessage request = null)
        {
            if (request == null)
            {
                return null;
            }
    
            if (request.Properties.ContainsKey("MS_OwinContext"))
            {
                return ((OwinContext) request.Properties["MS_OwinContext"]).Request.RemoteIpAddress;
            }
            return null;
        }
    

    【讨论】:

      【解决方案5】:

      我认为这是最清晰的解决方案,使用扩展方法:

      public static class HttpRequestMessageExtensions
      {
          private const string HttpContext = "MS_HttpContext";
          private const string RemoteEndpointMessage = "System.ServiceModel.Channels.RemoteEndpointMessageProperty";
      
          public static string GetClientIpAddress(this HttpRequestMessage request)
          {
              if (request.Properties.ContainsKey(HttpContext))
              {
                  dynamic ctx = request.Properties[HttpContext];
                  if (ctx != null)
                  {
                      return ctx.Request.UserHostAddress;
                  }
              }
      
              if (request.Properties.ContainsKey(RemoteEndpointMessage))
              {
                  dynamic remoteEndpoint = request.Properties[RemoteEndpointMessage];
                  if (remoteEndpoint != null)
                  {
                      return remoteEndpoint.Address;
                  }
              }
      
              return null;
          }
      }
      

      所以就像这样使用它:

      var ipAddress = request.GetClientIpAddress();
      

      我们在项目中使用它。

      来源/参考:Retrieving the client’s IP address in ASP.NET Web API

      【讨论】:

        【解决方案6】:

        回复这个 4 年前的帖子,因为这对我来说似乎过于复杂,至少如果您在 IIS 上托管。

        我是这样解决的:

        using System;
        using System.Net;
        using System.Web;
        using System.Web.Http;
        ...
        [HttpPost]
        [Route("ContactForm")]
        public IHttpActionResult PostContactForm([FromBody] ContactForm contactForm)
            {
                var hostname = HttpContext.Current.Request.UserHostAddress;
                IPAddress ipAddress = IPAddress.Parse(hostname);
                IPHostEntry ipHostEntry = Dns.GetHostEntry(ipAddress);
                ...
        

        与 OP 不同,这给了我客户端 IP 和客户端主机名,而不是服务器。也许他们从那时起就修复了这个错误?

        【讨论】:

          【解决方案7】:

          最好把它转换成HttpContextBase,这样你可以更容易地模拟和测试它

          public string GetUserIp(HttpRequestMessage request)
          {
              if (request.Properties.ContainsKey("MS_HttpContext"))
              {
                  var ctx = request.Properties["MS_HttpContext"] as HttpContextBase;
                  if (ctx != null)
                  {
                      return ctx.Request.UserHostAddress;
                  }
              }
          
              return null;
          }
          

          【讨论】:

          • 我用谷歌搜索了一下,其他人似乎同意这一点(转换为 HttpContextBase 而不是 HttpContextWrapper,因为 HttpContextBase 更容易模拟。)
          【解决方案8】:

          我的解决方案类似于 user1587439 的答案,但直接在控制器的实例上工作(而不是访问 HttpContext.Current)。

          在“观察”窗口中,我看到 this.RequestContext.WebRequest 包含“UserHostAddress”属性,但由于它依赖于 WebHostHttpRequestContext 类型(在“System.Web.Http”程序集内部) - 我无法直接访问,所以我使用反射直接访问它:

          string hostAddress = ((System.Web.HttpRequestWrapper)this.RequestContext.GetType().Assembly.GetType("System.Web.Http.WebHost.WebHostHttpRequestContext").GetProperty("WebRequest").GetMethod.Invoke(this.RequestContext, null)).UserHostAddress;

          我并不是说这是最好的解决方案。在框架升级的情况下(由于名称更改),使用反射可能会导致将来出现问题,但对于我的需要它是完美的

          【讨论】:

            【解决方案9】:
            string userRequest = System.Web.HttpContext.Current.Request.UserHostAddress;
            

            这对我有用。

            System.Web.HttpContext.Current.Request.UserHostName; 这个给我的回报与我从UserHostAddress 得到的回报相同。

            【讨论】: