當前位置 主頁 > 服務器問題 > Linux/apache問題 > 最大化 縮小

    Java獲取客戶端真實IP地址過程解析

    欄目:Linux/apache問題 時間:2020-01-17 20:24

    這篇文章主要介紹了Java獲取客戶端真實IP地址過程解析,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友可以參考下

    業務背景

    服務器端接收客戶端請求的時候,一般需要進行簽名驗證,客戶端IP限定等攔截,在進行IP限定的時候就需要獲取客戶端真實的IP。

    基礎知識

    訪問服務端的方式一般分為兩種:

    未經過代理,直接訪問服務器端;

    通過多級代理,最終到達服務器端(nginx,squid,haproxy)。

    客戶端請求信息都包含在HttpServletRequest中,對于第一種訪問方式可以通過getRemoteAddr()方法獲得客戶端真實IP,而另一種則行不通,但是可以通過x-forwarded-for獲得轉發后請求信息。當客戶端請求被轉發時,IP將會追加在其后并以英文逗號隔開,例如:10.47.103.13,4.2.2.2,10.96.112.230。

    請求中的參數:

      request.getHeader("x-forwarded-for") : 10.47.103.13,4.2.2.2,10.96.112.230
      request.getHeader("X-Real-IP") : 10.47.103.13
      request.getRemoteAddr():10.96.112.230

    客戶端訪問經過轉發,IP將會追加在其后并以逗號隔開。最終準確的客戶端信息為:

    x-forwarded-for 不為空,則為逗號前第一個IP ; X-Real-IP不為空,則為該IP ; 否則為getRemoteAddr() ;

    相關請求頭的解釋:

    X-Forwarded-For 記錄一個請求從客戶端出發到目標服務器過程中經歷的代理,或者負載平衡設備的IP。這是由緩存代理軟件 Squid 引入,用來表示 HTTP 請求端真實 IP,現在已經成為事實上的標準,被各大 HTTP 代理、負載均衡等轉發服務廣泛使用,并被寫入 RFC 7239(Forwarded HTTP Extension)標準之中。格式為X-Forwarded-For:client1,proxy1,proxy2,一般情況下,第一個ip為客戶端真實ip,后面的為經過的代理服務器的ip。現在大部分的代理都會加上這個請求頭。

    Proxy-Client-IP/WL- Proxy-Client-IP 這個一般是經過apache http服務器的請求才會有,用apache http做代理時一般會加上Proxy-Client-IP請求頭,而WL-Proxy-Client-IP是他的weblogic插件加上的頭。

    HTTP_CLIENT_IP 有些代理服務器會加上此請求頭。

    X-Real-IP nginx代理一般會加上此請求頭。

    獲取客戶端真實IP地址

    源碼:

    /**
     * 獲取客戶端的IP地址<br/>
     * 注意本地測試訪問項目地址時,瀏覽器請求不要用 localhost,請用本機IP;否則,取不到 IP
     *
     * @author east7
     * @date 2019年12月03日
     * @return String 真實IP地址
     */
    public static String getClientIpAddress(HttpServletRequest request) {
      // 獲取請求主機IP地址,如果通過代理進來,則透過防火墻獲取真實IP地址
      String headerName = "x-forwarded-for";
      String ip = request.getHeader(headerName);
      if (null != ip && ip.length() != 0 && !"unknown".equalsIgnoreCase(ip)) {
        // 多次反向代理后會有多個IP值,第一個IP才是真實IP,它們按照英文逗號','分割
        if (ip.indexOf(",") != -1) {
          ip = ip.split(",")[0];
        }
      }
      if (checkIp(ip)) {
        headerName = "Proxy-Client-IP";
        ip = request.getHeader(headerName);
      }
      if (checkIp(ip)) {
        headerName = "WL-Proxy-Client-IP";
        ip = request.getHeader(headerName);
      }
      if (checkIp(ip)) {
        headerName = "HTTP_CLIENT_IP";
        ip = request.getHeader(headerName);
      }
      if (checkIp(ip)) {
        headerName = "HTTP_X_FORWARDED_FOR";
        ip = request.getHeader(headerName);
      }
      if (checkIp(ip)) {
        headerName = "X-Real-IP";
        ip = request.getHeader(headerName);
      }
      if (checkIp(ip)) {
        headerName = "remote addr";
        ip = request.getRemoteAddr();
        // 127.0.0.1 ipv4, 0:0:0:0:0:0:0:1 ipv6
        if ("127.0.0.1".equals(ip) || "0:0:0:0:0:0:0:1".equals(ip)) {
          //根據網卡取本機配置的IP
          InetAddress inet = null;
          try {
            inet = InetAddress.getLocalHost();
          } catch (UnknownHostException e) {
            e.printStackTrace();
          }
          ip = inet.getHostAddress();
        }
      }
      logger.info("getClientIp IP is " + ip + ", headerName = " + headerName);
      return ip;
    }
    private static boolean checkIp(String ip) {
      if (null == ip || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
        return true;
      }
      return false;
    }
    
    下一篇:沒有了
777亚洲人成视频免费视频