CDN下获取用户真实IP


背景:

    前两天项目支付这块遇到个问题,支付成功率下跌的很厉害,最后查清原因是因为我们获取的”用户IP“被GC的风控拦截了,什么?拦截了,那还支付个毛啊,别急,待我接下来慢慢道出原因。根本原因是我们最近使用了CDN(Content Deliver Content 全称内容分发网络),CDN相当于是代理服务器,我们获取的所有用户IP其实都是CDN服务器的IP,也难怪被风控了呢,那具体怎么解决呢。
 
解决方案:
     首先运营商一般都会讲用户IP转发给Web应用,那么方法1:是使用运营商的插件来获取真实IP;方法2:通过判断 HTTP_X_FORWARDED_FOR 来判断到达Web应用的请求是否通过了代理;下面介绍下代码获取用户请求的真实IP:
/// <summary>
    /// 用于获取因用cdn无法获取用户真实IP的方法
    /// </summary>
    /// <returns></returns>
    public  string GetCdnIp()
    {
        try
        {
            if (HttpContext.Current == null
                || HttpContext.Current.Request == null
                || HttpContext.Current.Request.ServerVariables == null)
                return "";
            string customerIP = "";
            //CDN加速后取到的IP simone 090805
            customerIP = HttpContext.Current.Request.Headers["Cdn-Src-Ip"];
            if (!string.IsNullOrEmpty(customerIP))
            {
                return customerIP;
            }
            if (HttpContext.Current.Request.ServerVariables["HTTP_VIA"] != null)
            {
                customerIP = HttpContext.Current.Request.ServerVariables["HTTP_X_FORWARDED_FOR"];
                if (customerIP == null)
                    customerIP = HttpContext.Current.Request.ServerVariables["REMOTE_ADDR"];
            }
            else
            {
                customerIP = HttpContext.Current.Request.ServerVariables["REMOTE_ADDR"];
            }
            if (string.Compare(customerIP, "unknown", true) == 0)
                return HttpContext.Current.Request.UserHostAddress;
            return customerIP;

 

上面是网上的资料,再来看看咱本地的代码是如何获取的:
 
/// <summary>
        /// 获取用户真实IP
        /// </summary>
        /// <returns></returns>
        public static string GetIPFromHttpXForwardedFor()
        {
            HttpRequest request = HttpContext.Current.Request;
            string result = request.Headers["X-Forwarded-For"];
            if (!string.IsNullOrEmpty(result))
            {
                int index = result.IndexOf(".", StringComparison.Ordinal);
                //可能有代理   
                if (index == -1)//没有"."肯定是非IPv4格式   
                {
                    if (!IsIpAddress(result))//代理不是IP格式
                    {
                        result = null;
                    }
                }
                else
                {
                    //有",",估计多个代理。取第一个不是内网的IP。   
                    result = result.Replace(" ", "").Replace("\"", "");
                    string[] tempIps = result.Split(",;".ToCharArray());
                    foreach (string temp in tempIps)
                    {
                        if (IsIpAddress(temp)
                            && temp.Substring(0, 3) != "10."
                            && temp.Substring(0, 7) != "192.168"
                            && temp.Substring(0, 7) != "172.16.")
                        {
                            return temp;//找到不是内网的地址   
                        }
                    }
                }
            }
            if (string.IsNullOrEmpty(result))
            {
                result = request.ServerVariables["HTTP_X_FORWARDED_FOR"];
            }
            if (string.IsNullOrEmpty(result))
            {
                result = request.ServerVariables["REMOTE_ADDR"];
            }
            if (string.IsNullOrEmpty(result))
            {
                result = request.UserHostAddress;
            }
            if (result == "::1")
            {
                result = "127.0.0.1";
            }
            return result;
        }

 

思考
    在网上还看了一些资料,说 HTTP_X_FORWARDED_FOR 是扩展头,所以还没有成为一个标准,还有如果要将HTTP_X_FORWARDED_FOR作为用户的真实IP那么需要判断可信CDN的IP范围,才能保证你所获取的IP是真实的而不是伪造过的。
 
参考资料:
1. HTTP 请求头中的 X-Forwarded-For : https://imququ.com/post/x-forwarded-for-header-in-http.html
 


免责声明!

本站转载的文章为个人学习借鉴使用,本站对版权不负任何法律责任。如果侵犯了您的隐私权益,请联系本站邮箱yoyou2525@163.com删除。



 
粤ICP备18138465号  © 2018-2025 CODEPRJ.COM