首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >获取客户端IP地址: REMOTE_ADDR、HTTP_X_FORWARDED_FOR,还有什么有用的?

获取客户端IP地址: REMOTE_ADDR、HTTP_X_FORWARDED_FOR,还有什么有用的?
EN

Stack Overflow用户
提问于 2009-02-09 10:12:30
回答 4查看 176.4K关注 0票数 63

我知道这是一种标准的做法,要同时考虑这两个变量。当然,它们很容易被欺骗。我很好奇,您能期望这些值(特别是HTTP_X_FORWARDED_FOR)包含真正的信息,而不只是被打乱或剥离它们的值吗?

有谁有这方面的经验或统计数据吗?

对于获取客户端的IP地址的任务,是否还有其他有用的东西?

EN

回答 4

Stack Overflow用户

回答已采纳

发布于 2009-02-09 10:41:39

这取决于你网站的性质。

我碰巧在一些软件上工作,其中IP跟踪很重要,在parter站点消耗的字段中,我猜测大约20% - 40%的请求要么是可检测到的欺骗IP,要么是消隐的报头,这取决于一天中的时间和它们来自哪里。对于一个获得有机流量(即不是通过合作伙伴)的网站,我预计好IP的比例要高得多。

正如Kosi所说,小心你正在做的事情- in绝不是识别唯一访问者的可靠方法。

票数 31
EN

Stack Overflow用户

发布于 2012-03-27 12:38:34

我已经将Grant Burton的PHP代码移植到了一个可针对HttpRequestBase调用的ASP.Net静态方法。它可以选择跳过任何内网IP范围。

代码语言:javascript
复制
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)
    };
}
票数 10
EN

Stack Overflow用户

发布于 2009-02-09 12:02:05

IP +“用户代理”对于独立访问者来说是更好的选择。

票数 2
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/527638

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档