我正在尝试从ASP.NET MVC 5获取用户的IP地址。我已经查找了各种示例,例如:
他们都产生了相同的结果:用户被认为是网络内部的。我有朋友试试他们的手机(不在网络上)。这是我最近的尝试:
private static Logger _logger = LogManager.GetCurrentClassLogger();
public static bool IsIpInternal()
{
var ipAddress = HttpContext.Current.Request.UserHostAddress;
var logEvent = new LogEventInfo(LogLevel.Info, _logger.Name, ipAddress);
_logger.Log(logEvent);
try
{
if (ipAddress != null)
{
var ipParts = ipAddress.Split(new[] { "." }, StringSplitOptions.RemoveEmptyEntries)
.Select(int.Parse).ToArray();
var isDebug = System.Diagnostics.Debugger.IsAttached;
if (ipParts[0] == 10)
{
return true;
}
}
}
catch (Exception e)
{
logEvent = new LogEventInfo(LogLevel.Error, _logger.Name, e.Message);
_logger.Log(logEvent);
return false;
}
return false;
}
日志显示所有请求的10.xxx.xx.xxx
(基于日志)。这是一个内部地址,而不是连接到Web应用程序的客户端的IP。 IsIpInternal()
始终返回true。我做错了什么?
请注意,我忽略了192.168.x.x
和172.16.xxx.xxx
地址是内部的。
答案 0 :(得分:6)
如果您的网站位于负载均衡器后面,那么当您需要客户端的IP地址时,负载均衡器的IP地址就会出现一个常见问题。这是因为实际上负载均衡器是Web应用程序知道与之通信的唯一客户端。
有两种方法可以解决这个问题:
您可以配置负载均衡器以添加指定原始IP地址的其他HTTP标头(x-forwarded-for)。您需要修改您的网站以查看此标头而不是UserHostAddress,如下所示:
//var clientIP = HttpContext.Current.Request.UserHostAddress;
var clientIP = HttpContext.Current.Request.Headers["x-forwarded-for"];
注意:在某些情况下,x-forwarded-for标头实际上可以return a comma-delimited list of IP addresses。因此,要与这样的事件兼容,您可以改为编写:
var clientIP = HttpContext.Current.Request.Headers["x-forwarded-for"].Split(',')[0];
您可以通过复制IP标头数据包将某些LB配置为通过客户端IP。对于Citrix Netscaler,请参阅this article以获取更多信息。