Вопрос по java, http – Как я могу получить IP-адрес из заголовка HTTP в Java [дубликата]

14

This question already has an answer here:

How do I get the remote address of a client in servlet? 9 answers

Мне любопытно, есть ли какая-нибудь библиотека, которая уже занимается такими вещами, или я должен сделать это сам еще раз. Итак, дело в том, что я хочу получить поле IP-адреса из запроса заголовка HTTP посетителей на моем сервере, и сделать все это на Java? Любая помощь будет хорошей. Заранее спасибо.

Ваш Ответ

2   ответа
31

ИспользоватьgetHeader(String Name) методjavax.servlet.http.HttpServletRequest объект для получения значенияRemote_Addr переменная. Вот пример кода:

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

Если этот код возвращает пустую строку, используйте этот способ:

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

if (ipAddress == null) {
    ipAddress = request.getRemoteAddr();
}
Для распознавания страны / города используйте сервис GeoIP. Например, проверьте эту ссылку:maxmind.com/app/java
Спасибо большое, ребята! : D Это просто фантастика. Serenity Stack Holder
Это потрясающе! :) Спасибо, есть ли способ, который на основе данного IP-адреса может сделать вывод, из какой страны посетитель? Постскриптум Он будет помечен как лучший, потому что вы уже ответили на мой вопрос. Serenity Stack Holder
@Nepoxx проверить это:serverfault.com/questions/90725/…
Геокодировать IP-адрес:stackoverflow.com/questions/3232516/geocode-an-ip-address
8

Даже несмотря на то, что принятый ответ, за который проголосовали высоко, я хотел бы предложить альтернативу и указать на недостатки принятого ответа.

request.getHeader("Remote_Addr") являетсяуказанный вернуть точно так же, какrequest.getRemoteAddr(), Следовательно, нет смысла проверять оба. Также обратите внимание, чтоgetRemoteAddr это методjavax.servlet.ServletRequest (т. е. HTTP-агностик) в то время какgetHeader вjavax.servlet.http.HttpServletRequest.

Кроме того, некоторые прокси используютClient-IP скорее, чемX-Forwarded-For, Для обсуждения см.https://stackoverflow.com/a/7446010/131929.

Я не знаю, насколько надежно использованиеHTTP_X_FORWARDED_FOR надX-Forwarded-For является. В Java я бы предпочел использовать прямую краткую форму. Для обсуждения см.https://stackoverflow.com/a/3834169/131929, Верхний / нижний регистр не имеет значения, потому чтоgetHeader являетсяуказанный быть случаемinчувствительны.

Java alternative

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 alternative

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;
}
Ваше решение элегантно, и я собираюсь использовать это. UpVote
X-Forwarded-For может содержать список IP-адресов прокси, разделенных запятыми, поэтому сначала я бы разделил строку.

Похожие вопросы