ASP.NET Web API 2.1获取客户端IP地址

136

你好,我需要获取请求Web API中某个方法的客户端IP。我尝试使用这里的代码,但它总是返回服务器本地IP,有什么正确的方法可以获取客户端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;
        }
    }

这个扩展方法对我很有效。(我没有使用 OWIN 或其他不寻常的东西。) - Nate Barbettini
感谢您注明出处。已编辑。 - Stefano Mtangoo
可能是获取远程主机的IP地址的重复问题。 - Michael Freidgeim
9个回答

145

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

参考资料:通过ASP.NET Web API获取客户端IP地址

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;
                }
           }
     }
}

另一种做法如下。

参考:如何获取客户端IP地址

适用于Web托管版本。

string clientAddress = HttpContext.Current.Request.UserHostAddress;

对于自托管

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

76

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


31
请注意,此方法仅适用于使用 Owin 的情况 - https://msdn.microsoft.com/en-us/library/system.net.http.owinhttprequestmessageextensions.getowincontext(v=vs.118).aspx - Chandramouleswaran Ravichandra

20

尝试使用以下方法获取IP地址

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

1
@DenisBabarykin 我认为应该可以,它会返回服务器变量REMOTE_ADDR中的IP地址。 - user1587439

12

回复这篇四年前的帖子,因为对我来说似乎过于复杂,至少如果你正在使用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和客户端主机名,而不是服务器。也许自那时以来他们已经修复了这个漏洞?


11

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

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();

我们在我们的项目中使用它。

来源/参考: 在ASP.NET Web API中检索客户端IP地址


10

如果您正在使用OWIN Self-host 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
最好将其转换为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;
}

1
我在谷歌上搜索了一下,其他人似乎也认同这个观点(将类型转换为HttpContextBase而不是HttpContextWrapper,因为HttpContextBase更容易进行模拟测试)。 - Dave Clausen

2
我的解决方案与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;
我并不是说这是最好的解决方案。使用反射可能会在将来出现问题,例如框架升级(由于名称更改),但对于我的需求来说,它是完美的。

2
string userRequest = System.Web.HttpContext.Current.Request.UserHostAddress;

这对我有用。

System.Web.HttpContext.Current.Request.UserHostName; 这个返回给我的结果和 UserHostAddress 返回的相同。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接