我们有请求。UserHostAddress在ASP. ASP. ASP中获取IP地址。NET,但这通常是用户的ISP的IP地址,而不是用户点击链接的机器IP地址。如何获取真实IP地址?
例如,在Stack Overflow用户配置文件中,它是:“上次帐户活动:4小时前从86.123.127.8开始”,但我的机器IP地址有点不同。Stack Overflow如何获得这个地址?
在一些web系统中,出于某些目的有一个IP地址检查。例如,对于某个IP地址,每24小时用户只能点击5次下载链接吗?这个IP地址应该是唯一的,而不是针对一个拥有大量客户端或互联网用户的ISP。
我听懂了吗?
我想我应该和大家分享我的经验。好吧,我看到在某些情况下REMOTE_ADDR将不会得到你正在寻找的东西。例如,如果你在后台有一个负载均衡器,如果你试图获取客户端的IP,那么你就会遇到麻烦。我用我的IP屏蔽软件检查过了,我还和我在不同大洲的同事们检查过了。这就是我的解。
当我想知道一个客户端的IP时,我试图选择每一个可能的证据,这样我就可以确定它们是否唯一:
在这里,我发现了另一个server -var,如果你想获得客户端的确切IP,它可以帮助你。所以我使用:HTTP_X_CLUSTER_CLIENT_IP
HTTP_X_CLUSTER_CLIENT_IP总是得到客户端的确切IP。在任何情况下,如果它不给你的值,你应该然后寻找HTTP_X_FORWARDED_FOR,因为它是第二个最好的候选人,让你的客户端IP,然后REMOTE_ADDR变量,可能或可能不返回你的IP,但对我来说,拥有这三个是我发现最好的东西来监控他们。
我希望这能帮助到一些人。
到目前为止,所有的响应都考虑了非标准化但非常常见的X-Forwarded-For报头。有一个标准化的转发头,它有点难以解析。一些例子如下:
Forwarded: for="_gazonk"
Forwarded: For="[2001:db8:cafe::17]:4711"
Forwarded: for=192.0.2.60;proto=http;by=203.0.113.43
Forwarded: for=192.0.2.43, for=198.51.100.17
我已经编写了一个类,在确定客户端的IP地址时考虑这两个头。
using System;
using System.Web;
namespace Util
{
public static class IP
{
public static string GetIPAddress()
{
return GetIPAddress(new HttpRequestWrapper(HttpContext.Current.Request));
}
internal static string GetIPAddress(HttpRequestBase request)
{
// handle standardized 'Forwarded' header
string forwarded = request.Headers["Forwarded"];
if (!String.IsNullOrEmpty(forwarded))
{
foreach (string segment in forwarded.Split(',')[0].Split(';'))
{
string[] pair = segment.Trim().Split('=');
if (pair.Length == 2 && pair[0].Equals("for", StringComparison.OrdinalIgnoreCase))
{
string ip = pair[1].Trim('"');
// IPv6 addresses are always enclosed in square brackets
int left = ip.IndexOf('['), right = ip.IndexOf(']');
if (left == 0 && right > 0)
{
return ip.Substring(1, right - 1);
}
// strip port of IPv4 addresses
int colon = ip.IndexOf(':');
if (colon != -1)
{
return ip.Substring(0, colon);
}
// this will return IPv4, "unknown", and obfuscated addresses
return ip;
}
}
}
// handle non-standardized 'X-Forwarded-For' header
string xForwardedFor = request.Headers["X-Forwarded-For"];
if (!String.IsNullOrEmpty(xForwardedFor))
{
return xForwardedFor.Split(',')[0];
}
return request.UserHostAddress;
}
}
}
下面是我用来验证我的解决方案的一些单元测试:
using System.Collections.Specialized;
using System.Web;
using Microsoft.VisualStudio.TestTools.UnitTesting;
namespace UtilTests
{
[TestClass]
public class IPTests
{
[TestMethod]
public void TestForwardedObfuscated()
{
var request = new HttpRequestMock("for=\"_gazonk\"");
Assert.AreEqual("_gazonk", Util.IP.GetIPAddress(request));
}
[TestMethod]
public void TestForwardedIPv6()
{
var request = new HttpRequestMock("For=\"[2001:db8:cafe::17]:4711\"");
Assert.AreEqual("2001:db8:cafe::17", Util.IP.GetIPAddress(request));
}
[TestMethod]
public void TestForwardedIPv4()
{
var request = new HttpRequestMock("for=192.0.2.60;proto=http;by=203.0.113.43");
Assert.AreEqual("192.0.2.60", Util.IP.GetIPAddress(request));
}
[TestMethod]
public void TestForwardedIPv4WithPort()
{
var request = new HttpRequestMock("for=192.0.2.60:443;proto=http;by=203.0.113.43");
Assert.AreEqual("192.0.2.60", Util.IP.GetIPAddress(request));
}
[TestMethod]
public void TestForwardedMultiple()
{
var request = new HttpRequestMock("for=192.0.2.43, for=198.51.100.17");
Assert.AreEqual("192.0.2.43", Util.IP.GetIPAddress(request));
}
}
public class HttpRequestMock : HttpRequestBase
{
private NameValueCollection headers = new NameValueCollection();
public HttpRequestMock(string forwarded)
{
headers["Forwarded"] = forwarded;
}
public override NameValueCollection Headers
{
get { return this.headers; }
}
}
}