我明白這是一個標準的做法,看看這兩個變量。當然,他們很容易被欺騙。我很好奇你多久可以期望這些值(特別是HTTP_X_FORWARDED_FOR
)能夠包含真實信息,而不僅僅是被混淆或被剝奪了價值?獲取客戶端IP地址:REMOTE_ADDR,HTTP_X_FORWARDED_FOR,還有什麼用處?
任何人都有這方面的經驗或統計資料?
對於獲取客戶端IP地址的任務還有什麼可以使用嗎?
我明白這是一個標準的做法,看看這兩個變量。當然,他們很容易被欺騙。我很好奇你多久可以期望這些值(特別是HTTP_X_FORWARDED_FOR
)能夠包含真實信息,而不僅僅是被混淆或被剝奪了價值?獲取客戶端IP地址:REMOTE_ADDR,HTTP_X_FORWARDED_FOR,還有什麼用處?
任何人都有這方面的經驗或統計資料?
對於獲取客戶端IP地址的任務還有什麼可以使用嗎?
這取決於你的網站的性質。
我碰巧在一些IP跟蹤非常重要的軟件上工作,並且在參與者站點使用的字段中,我猜想有20%-40%的請求要麼是可檢測到的IP地址,要麼是標題空白,取決於在一天的時間和他們來自哪裏。對於獲得有機流量的網站(即不通過合作伙伴),我希望有更好的IP比例。
正如Kosi所說,要小心你在做什麼 - IPs絕不是確定獨特訪客的可靠方法。
對您的問題沒有真正的答案,但:
通常依靠客戶端IP地址在我看來不是一個好的做法,因爲它不能用於以獨特的方式識別客戶端。在路上
的問題是,有相當多的場景中的IP並沒有真正對齊到客戶端:
我不能提供一個y關於多少個IP地址的平均值的統計可靠,但我可以告訴你幾乎不可能分辨給定的IP地址是否是真正的客戶端地址。
哪些是「最佳實踐」*以獨特的方式識別客戶*? ***清單***:_Not use clients IP address_ – Kiquenet 2016-11-15 11:51:09
除了REMOTE_ADDR
和HTTP_X_FORWARDED_FOR
有可以設置諸如其他一些標題:
HTTP_CLIENT_IP
HTTP_X_FORWARDED_FOR
可以用逗號分隔的IP地址列表HTTP_X_FORWARDED
HTTP_X_CLUSTER_CLIENT_IP
HTTP_FORWARDED_FOR
HTTP_FORWARDED
我發現下面的網站有用的代碼:
http://www.grantburton.com/?p=97
這個列表是否完整,意思是覆蓋了所有代理的90%以上? – basZero 2014-01-10 17:13:41
我已經轉移了格蘭特·波頓的PHP代碼到一個ASP.Net靜態方法調用針對HttpRequestBase。它可以選擇跳過任何專用IP範圍。
public static class ClientIP
{
// based on http://www.grantburton.com/2008/11/30/fix-for-incorrect-ip-addresses-in-wordpress-comments/
public static string ClientIPFromRequest(this HttpRequestBase request, bool skipPrivate)
{
foreach (var item in s_HeaderItems)
{
var ipString = request.Headers[item.Key];
if (String.IsNullOrEmpty(ipString))
continue;
if (item.Split)
{
foreach (var ip in ipString.Split(','))
if (ValidIP(ip, skipPrivate))
return ip;
}
else
{
if (ValidIP(ipString, skipPrivate))
return ipString;
}
}
return request.UserHostAddress;
}
private static bool ValidIP(string ip, bool skipPrivate)
{
IPAddress ipAddr;
ip = ip == null ? String.Empty : ip.Trim();
if (0 == ip.Length
|| false == IPAddress.TryParse(ip, out ipAddr)
|| (ipAddr.AddressFamily != AddressFamily.InterNetwork
&& ipAddr.AddressFamily != AddressFamily.InterNetworkV6))
return false;
if (skipPrivate && ipAddr.AddressFamily == AddressFamily.InterNetwork)
{
var addr = IpRange.AddrToUInt64(ipAddr);
foreach (var range in s_PrivateRanges)
{
if (range.Encompasses(addr))
return false;
}
}
return true;
}
/// <summary>
/// Provides a simple class that understands how to parse and
/// compare IP addresses (IPV4) ranges.
/// </summary>
private sealed class IpRange
{
private readonly UInt64 _start;
private readonly UInt64 _end;
public IpRange(string startStr, string endStr)
{
_start = ParseToUInt64(startStr);
_end = ParseToUInt64(endStr);
}
public static UInt64 AddrToUInt64(IPAddress ip)
{
var ipBytes = ip.GetAddressBytes();
UInt64 value = 0;
foreach (var abyte in ipBytes)
{
value <<= 8; // shift
value += abyte;
}
return value;
}
public static UInt64 ParseToUInt64(string ipStr)
{
var ip = IPAddress.Parse(ipStr);
return AddrToUInt64(ip);
}
public bool Encompasses(UInt64 addrValue)
{
return _start <= addrValue && addrValue <= _end;
}
public bool Encompasses(IPAddress addr)
{
var value = AddrToUInt64(addr);
return Encompasses(value);
}
};
private static readonly IpRange[] s_PrivateRanges =
new IpRange[] {
new IpRange("0.0.0.0","2.255.255.255"),
new IpRange("10.0.0.0","10.255.255.255"),
new IpRange("127.0.0.0","127.255.255.255"),
new IpRange("169.254.0.0","169.254.255.255"),
new IpRange("172.16.0.0","172.31.255.255"),
new IpRange("192.0.2.0","192.0.2.255"),
new IpRange("192.168.0.0","192.168.255.255"),
new IpRange("255.255.255.0","255.255.255.255")
};
/// <summary>
/// Describes a header item (key) and if it is expected to be
/// a comma-delimited string
/// </summary>
private sealed class HeaderItem
{
public readonly string Key;
public readonly bool Split;
public HeaderItem(string key, bool split)
{
Key = key;
Split = split;
}
}
// order is in trust/use order top to bottom
private static readonly HeaderItem[] s_HeaderItems =
new HeaderItem[] {
new HeaderItem("HTTP_CLIENT_IP",false),
new HeaderItem("HTTP_X_FORWARDED_FOR",true),
new HeaderItem("HTTP_X_FORWARDED",false),
new HeaderItem("HTTP_X_CLUSTER_CLIENT_IP",false),
new HeaderItem("HTTP_FORWARDED_FOR",false),
new HeaderItem("HTTP_FORWARDED",false),
new HeaderItem("HTTP_VIA",false),
new HeaderItem("REMOTE_ADDR",false)
};
}
如果你是一個代理之後,你應該使用X-Forwarded-For
:http://en.wikipedia.org/wiki/X-Forwarded-For
它與廣泛支持的IETF draft standard:
的X轉發,對於現場被大多數支持代理服務器, 包括Squid,Apache mod_proxy,Pound,HAProxy,Varnish緩存, Radware的AppDirector和Alteon ADC,ADC-VX,a網絡的Maestro,網頁調整器和Websense網絡安全網關。該公司的網絡服務器,網絡調節器和Websense網絡安全網關。
如果不是這樣,這裏有一些其他常見的頭我見過:
請注意,當HTTP請求標頭添加到ServerVariables集合時,問題和答案都使用HTTP_前綴,該前綴是ASP.NET v1.0-v4.x的特定實現細節。另一個例子是REMOTE_ADDR,在ASP.NET Core中有它自己的API。 https://stackoverflow.com/questions/28664686/how-do-i-get-client-ip-address-in-asp-net-core – yzorg 2017-12-11 14:24:10