1. 程式人生 > >Java Web 獲取客戶端真實IP

Java Web 獲取客戶端真實IP

發生的場景:伺服器端接收客戶端請求的時候,一般需要進行簽名驗證,客戶端IP限定等情況,在進行客戶端IP限定的時候,需要首先獲取該真實的IP。一般分為兩種情況:

方式一、客戶端未經過代理,直接訪問伺服器端(nginx,squid,haproxy);

在這裡插入圖片描述

方式二、客戶端通過多級代理,最終到達伺服器端(nginx,squid,haproxy);

在這裡插入圖片描述

客戶端請求資訊都包含在HttpServletRequest中,可以通過方法getRemoteAddr()獲得該客戶端IP。此時如果在使用方式一形式,可以直接獲得該客戶端真實IP。而如果是方式二中通過代理的形式,此時經過多級反向的代理,通過方法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() ;

程式碼示例:

/** 
     * 獲取使用者真實IP地址,不使用request.getRemoteAddr()的原因是有可能使用者使用了代理軟體方式避免真實IP地址, 
     * 可是,如果通過了多級反向代理的話,X-Forwarded-For的值並不止一個,而是一串IP值 
     *  
     * @return ip
     */
    private String getIpAddr(HttpServletRequest request) {
        String ip = request.getHeader("x-forwarded-for"); 
        System.out.println("x-forwarded-for ip: " + ip);
        if (ip != null && ip.length() != 0 && !"unknown".equalsIgnoreCase(ip)) {  
            // 多次反向代理後會有多個ip值,第一個ip才是真實ip
            if( ip.indexOf(",")!=-1 ){
                ip = ip.split(",")[0];
            }
        }  
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {  
            ip = request.getHeader("Proxy-Client-IP");  
            System.out.println("Proxy-Client-IP ip: " + ip);
        }  
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {  
            ip = request.getHeader("WL-Proxy-Client-IP");  
            System.out.println("WL-Proxy-Client-IP ip: " + ip);
        }  
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {  
            ip = request.getHeader("HTTP_CLIENT_IP");  
            System.out.println("HTTP_CLIENT_IP ip: " + ip);
        }  
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {  
            ip = request.getHeader("HTTP_X_FORWARDED_FOR");  
            System.out.println("HTTP_X_FORWARDED_FOR ip: " + ip);
        }  
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {  
            ip = request.getHeader("X-Real-IP");  
            System.out.println("X-Real-IP ip: " + ip);
        }  
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {  
            ip = request.getRemoteAddr();  
            System.out.println("getRemoteAddr ip: " + ip);
        } 
        System.out.println("獲取客戶端ip: " + ip);
        return ip;  
    }