2012-04-28 56 views
11

我很好奇是否有任何庫已經處理過這種東西,或者我必須再次自行完成。所以,我想從我的服務器上的訪問者HTTP頭請求中獲取IP地址字段,並在Java中完成整個事情?你能幫忙的話,我會很高興。 在此先感謝。如何從Java的HTTP標頭中檢索IP地址

回答

28

使用javax.servlet.http.HttpServletRequest對象的getHeader(String Name)方法檢索Remote_Addr變量的值。下面是示例代碼:

String ipAddress = request.getHeader("Remote_Addr"); 

如果這個代碼返回空字符串,然後用這個辦法:

String ipAddress = request.getHeader("HTTP_X_FORWARDED_FOR"); 

if (ipAddress == null) { 
    ipAddress = request.getRemoteAddr(); 
} 
+1

這是真棒! :)謝謝,有沒有基於給定IP地址的任何方法可以從訪問者的國家得出結論?附:將它標爲最好的,因爲你已經在我的問答中回答了。 – 2012-04-28 11:45:43

+1

要認識國家/城市使用GeoIP服務。例如檢查這個鏈接:http://www.maxmind.com/app/java – 2012-04-28 11:47:27

+2

Geocode一個IP地址:http://stackoverflow.com/questions/3232516/geocode-an-ip-address – 2012-04-28 11:47:59

7

即使有這麼一直備受upvoted一個公認的答案,我想建議的選擇並指出接受答案的缺點。

request.getHeader("Remote_Addr")specified返回與request.getRemoteAddr()完全相同。因此,檢查兩者是沒有意義的。還請注意getRemoteAddrjavax.servlet.ServletRequest(即HTTP不可知)的方法,而getHeaderjavax.servlet.http.HttpServletRequest中。

此外,一些代理使用Client-IP而不是X-Forwarded-For。有關討論,請參閱https://stackoverflow.com/a/7446010/131929

我不知道使用HTTP_X_FORWARDED_FORX-Forwarded-For有多可靠。在Java中,我寧願使用直接的簡寫形式。有關討論,請參閱https://stackoverflow.com/a/3834169/131929。大寫/小寫沒有區別,因爲getHeaderspecified必須是敏感。

Java的替代

public final class ClientIpAddress { 

    // CHECKSTYLE:OFF 
    // https://stackoverflow.com/a/11327345/131929 
    private static Pattern PRIVATE_ADDRESS_PATTERN = Pattern.compile(
     "(^127\\.)|(^192\\.168\\.)|(^10\\.)|(^172\\.1[6-9]\\.)|(^172\\.2[0-9]\\.)|(^172\\.3[0-1]\\.)|(^::1$)|(^[fF][cCdD])", 
     Pattern.CANON_EQ); 
    // CHECKSTYLE:ON 

    private ClientIpAddress() { 
    } 

    /** 
    * Extracts the "real" client IP address from the request. It analyzes request headers 
    * {@code REMOTE_ADDR}, {@code X-Forwarded-For} as well as {@code Client-IP}. Optionally 
    * private/local addresses can be filtered in which case an empty string is returned. 
    * 
    * @param request HTTP request 
    * @param filterPrivateAddresses true if private/local addresses (see 
    * https://en.wikipedia.org/wiki/Private_network#Private_IPv4_address_spaces and 
    * https://en.wikipedia.org/wiki/Unique_local_address) should be filtered i.e. omitted 
    * @return IP address or empty string 
    */ 
    public static String getFrom(HttpServletRequest request, boolean filterPrivateAddresses) { 
    String ip = request.getRemoteAddr(); 

    String headerClientIp = request.getHeader("Client-IP"); 
    String headerXForwardedFor = request.getHeader("X-Forwarded-For"); 
    if (StringUtils.isEmpty(ip) && StringUtils.isNotEmpty(headerClientIp)) { 
     ip = headerClientIp; 
    } else if (StringUtils.isNotEmpty(headerXForwardedFor)) { 
     ip = headerXForwardedFor; 
    } 
    if (filterPrivateAddresses && isPrivateOrLocalAddress(ip)) { 
     return StringUtils.EMPTY; 
    } else { 
     return ip; 
    } 
    } 

    private static boolean isPrivateOrLocalAddress(String address) { 
    Matcher regexMatcher = PRIVATE_ADDRESS_PATTERN.matcher(address); 
    return regexMatcher.matches(); 
    } 
} 

PHP替代

function getIp() 
{ 
    $ip = $_SERVER['REMOTE_ADDR']; 

    if (empty($ip) && !empty($_SERVER['HTTP_CLIENT_IP'])) { 
     $ip = $_SERVER['HTTP_CLIENT_IP']; 
    } elseif (!empty($_SERVER['HTTP_X_FORWARDED_FOR'])) { 
     // omit private IP addresses which a proxy forwarded 
     $tmpIp = $_SERVER['HTTP_X_FORWARDED_FOR']; 
     $tmpIp = filter_var(
      $tmpIp, 
      FILTER_VALIDATE_IP, 
      FILTER_FLAG_IPV4 | FILTER_FLAG_NO_PRIV_RANGE | FILTER_FLAG_NO_RES_RANGE 
     ); 
     if ($tmpIp != false) { 
      $ip = $tmpIp; 
     } 
    } 
    return $ip; 
} 
+0

你的解決方案是優雅的,我gona使用這個。 UpVote – Mubasher 2016-09-19 11:36:23

+0

X-Forwarded-For可以包含逗號分隔的代理IP地址列表,所以我會先分割字符串。 – 2018-02-08 22:12:28