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