2012-04-28 120 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