Подтвердить что ты не робот

Как получить удаленный адрес клиента в сервлет?

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

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

4b9b3361

Ответ 1

попробуйте следующее:

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;  
    }  

Ответ 2

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

Ответ 3

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

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

Вы не можете сделать это значимым образом.

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

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

Ответ 5

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

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

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

Ответ 6

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

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) {
    return IP_HEADERS.stream()
        .map(request::getHeader)
        .filter(Objects::nonNull)
        .filter(ip -> !ip.isEmpty() && !ip.equalsIgnoreCase("unknown"))
        .findFirst()
        .orElseGet(request::getRemoteAddr);
}

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

Ответ 7

Заголовок

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

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

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

Ответ 8

String ipAddress = request.getHeader("x-forwarded-for");
        if (ipAddress == null) {
            ipAddress = request.getHeader("X_FORWARDED_FOR");
            if (ipAddress == null){
                ipAddress = request.getRemoteAddr();
            }
        }

Ответ 9

Почему я думаю, что мы должны сначала попытаться получить 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 "";
    }

Ответ 10

InetAddress inetAddress = InetAddress.getLocalHost();
String ip = inetAddress.getHostAddress();