如何从Java中的HTTP标头中检索IP地址

Ser*_*der 15 java http httpwebrequest http-headers

我很好奇是否有任何图书馆已经处理过这种东西,或者我必须再次自己做.那么,问题是我想从我的服务器上的访问者HTTP头请求中获取IP地址字段,并用Java完成整个事情?你能帮忙的话,我会很高兴.提前致谢.

小智 33

使用对象的getHeader(String Name)方法javax.servlet.http.HttpServletRequest来检索Remote_Addr变量的值.以下是示例代码:

String ipAddress = request.getHeader("Remote_Addr");
Run Code Online (Sandbox Code Playgroud)

如果此代码返回空字符串,则使用以下方式:

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

if (ipAddress == null) {
    ipAddress = request.getRemoteAddr();
}
Run Code Online (Sandbox Code Playgroud)

  • 识别国家/城市使用GeoIP服务.例如,请查看以下链接:http://www.maxmind.com/app/java (2认同)
  • 地理编码IP地址:http://stackoverflow.com/questions/3232516/geocode-an-ip-address (2认同)

Mar*_*tör 9

即使有一个被高度赞成的公认答案,我也想提出一个替代方案并指出已接受答案的缺点.

request.getHeader("Remote_Addr")指定返回与完全相同request.getRemoteAddr().因此,检查两者都没有意义.还要注意的是getRemoteAddr是的方法javax.servlet.ServletRequest(即,HTTP无关),而getHeaderjavax.servlet.http.HttpServletRequest.

此外,一些代理使用Client-IP而不是X-Forwarded-For.有关讨论,请参阅/sf/answers/521220731/.

我不知道使用HTTP_X_FORWARDED_FORover X-Forwarded-For是多么可靠.在Java中,我宁愿使用直接的简短形式.有关讨论,请参阅/sf/answers/268391861/.大写/小写没有区别,因为getHeader指定成情况是敏感的.

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();
  }
}
Run Code Online (Sandbox Code Playgroud)

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;
}
Run Code Online (Sandbox Code Playgroud)