Как получить удаленный адрес клиента в сервлете? - PullRequest
63 голосов
/ 13 января 2011

Можно ли как-нибудь получить исходный IP-адрес клиента, приходящего на сервер?Я могу использовать request.getRemoteAddr(), но я всегда получаю IP-адрес прокси-сервера или веб-сервера.

Я хотел бы знать IP-адрес, который клиент использует для подключения ко мне.Есть ли что-нибудь, что я мог бы получить?

Ответы [ 10 ]

101 голосов
/ 10 марта 2013

попробуйте это:

public static String getClientIpAddr(HttpServletRequest request) {  
        String ip = request.getHeader("X-Forwarded-For");  
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {  
            ip = request.getHeader("Proxy-Client-IP");  
        }  
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {  
            ip = request.getHeader("WL-Proxy-Client-IP");  
        }  
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {  
            ip = request.getHeader("HTTP_CLIENT_IP");  
        }  
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {  
            ip = request.getHeader("HTTP_X_FORWARDED_FOR");  
        }  
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {  
            ip = request.getRemoteAddr();  
        }  
        return ip;  
    }  
10 голосов
/ 13 января 2011

request.getRemoteAddr() это путь. Похоже ваш прокси меняет исходный IP. Когда некоторые прокси-серверы делают это, они добавляют исходный IP-адрес в некоторый пользовательский заголовок http. Используйте request.getHeaderNames() и request.getHeaders(name) и распечатайте их все, чтобы увидеть, нет ли ничего интересного. Как X-CLIENT-IP (сделал это, но они выглядят так)

5 голосов
/ 06 ноября 2013

Лучшее решение, которое я когда-либо использовал

public String getIpAddr(HttpServletRequest request) {      
   String ip = request.getHeader("x-forwarded-for");      
   if(ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {      
       ip = request.getHeader("Proxy-Client-IP");      
   }      
   if(ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {      
       ip = request.getHeader("WL-Proxy-Client-IP");      
   }      
   if(ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {      
       ip = request.getRemoteAddr();      
   }      
   return ip;      
} 
4 голосов
/ 15 июля 2014

Так как обычно это проблема развертывания, а не проблема приложения, другим подходом будет правильная настройка контейнера приложения. После настройки контейнер заботится о проверке соответствующего заголовка, и ваше приложение продолжает использовать request.getRemoteAddr().

.

Например, в Tomcat вы можете использовать Удаленный IP-клапан . Я бы предположил, что большинство серверов приложений имеют аналогичную функциональность.

Контейнер также может позаботиться о том, чтобы ваш балансировщик внешней нагрузки прерывал SSL-соединения и пересылал запрос на сервер приложений по HTTP. Это важно, когда вашему приложению нужно сгенерировать URL для себя.

4 голосов
/ 13 января 2011

Вы не можете сделать это осмысленно.

Прокси-сервер может добавлять или не добавлять заголовок для прокси-сервера, но во многих случаях это в любом случае будет только внутренний адрес, поэтому он будет для вас бессмысленным. Большинство прокси на периферии организации в любом случае настроены так, чтобы как можно меньше раскрывать внутреннюю информацию сети.

Для чего вы собираетесь использовать эту информацию?

1 голос
/ 10 июля 2013

Заголовок запроса «x-forwarded-for» содержит исходный IP-адрес клиента, если используется прокси или балансировщик нагрузки. Но я думаю, что не все прокси / lb добавляет этот заголовок.

Вот код Java для разбора заголовка: http://www.codereye.com/2010/01/get-real-ip-from-request-in-java.html

Если этот заголовок отсутствует, я бы продолжил, как @Bozho предлагает

0 голосов
/ 17 апреля 2019

Почему я думаю, что мы должны сначала попытаться получить IP из заголовка 'X-Forwarded-For'? Если вы получаете от request.getRemoteAddr(), это может быть реальный ip клиента или ip последнего прокси, который перенаправляет запрос . Таким образом, мы не можем сказать, к какому состоянию оно относится. Однако, если в заголовке установлено значение 'X-Forwarded-For' , ip клиента обязательно будет самой левой частью того, что вы получаете от него.

    /**
     * Try to get real ip from request:
     * <ul>
     *     <li>try X-Forwarded-For</li>
     *     <li>try remote address</li>
     * </ul>
     *
     * @param request    request
     * @return real ip or ""
     */
    private String tryGetRealIp(HttpServletRequest request) {
        // X-Forwarded-For: <client>, <proxy1>, <proxy2>
        // If a request goes through multiple proxies, the IP addresses of each successive proxy is listed.
        // This means, the right-most IP address is the IP address of the most recent proxy and
        // the left-most IP address is the IP address of the originating client.
        String forwards = request.getHeader("X-Forwarded-For");
        if (StringUtils.isNotBlank(forwards)) {
            // The left-most IP must be client ip
            String ip = StringUtils.substringBefore(forwards, ",");
            return ip;
        } else if (StringUtils.isNotBlank(request.getRemoteAddr())) {
            // this could be real client ip or last proxy ip which forwards the request
            return request.getRemoteAddr();
        }
        return "";
    }
0 голосов
/ 18 января 2019

Почему бы не использовать более элегантное решение, подобное этому?

private static final List<String> IP_HEADERS = Arrays.asList("X-Forwarded-For", "Proxy-Client-IP", "WL-Proxy-Client-IP", "HTTP_CLIENT_IP", "HTTP_X_FORWARDED_FOR");

public static String getClientIpAddr(HttpServletRequest request) {
    for (String ipHeader : IP_HEADERS) {
        String ip = request.getHeader(ipHeader);
        if (ip != null && !ip.isEmpty() && !ip.equalsIgnoreCase("unknown")) {
            return ip;
        }
    }
    return request.getRemoteAddr();
}

Дублируйте свой код!

0 голосов
/ 24 июля 2015
InetAddress inetAddress = InetAddress.getLocalHost();
String ip = inetAddress.getHostAddress();
0 голосов
/ 06 июня 2013
String ipAddress = request.getHeader("x-forwarded-for");
        if (ipAddress == null) {
            ipAddress = request.getHeader("X_FORWARDED_FOR");
            if (ipAddress == null){
                ipAddress = request.getRemoteAddr();
            }
        }
...