Как получить удаленный адрес клиента в сервлет?
Есть ли способ получить исходный IP-адрес клиента, поступающего на сервер? Я могу использовать request.getRemoteAddr()
, но я всегда получаю IP-адрес прокси-сервера или веб-сервера.
Я хотел бы знать IP-адрес, который клиент использует для подключения ко мне. В любом случае, я могу это получить?
попробуй это:
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; }
request.getRemoteAddr()
– это способ. Похоже, ваш прокси изменяет IP-адрес источника. Когда некоторые прокси делают это, они добавляют исходный IP-адрес в какой-то пользовательский HTTP-заголовок. Используйте request.getHeaderNames()
и request.getHeaders(name)
и распечатайте их все, чтобы узнать, нет ли чего-нибудь интересного. Как X-CLIENT-IP
(сделал это, но они выглядят так)
Вы не можете сделать это значимым образом.
Прокси может добавлять или не добавлять заголовок прокси-заголовка, но во многих случаях это будет внутренний адрес, так что это будет бессмысленно для вас. Большинство прокси-серверов на краю организации настроены так, чтобы как можно меньше выявлять внутренние сети.
На что вы собираетесь использовать эту информацию?
Лучшее решение, которое я когда-либо использовал
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; }
Поскольку это, как правило, проблема развертывания, а не проблема приложения, другой подход заключается в том, чтобы настроить контейнер приложения соответствующим образом. После настройки контейнер позаботится о проверке соответствующего заголовка, и ваше приложение продолжает использовать request.getRemoteAddr()
.
Например, в Tomcat вы можете использовать Remote IP Valve . Я бы предположил, что большинство серверов приложений имеют аналогичную функциональность.
Контейнер также может позаботиться о том, чтобы ваш балансировщик нагрузки на фронте прекратил соединение SSL, перенаправляя запрос на сервер приложений через HTTP. Это важно, когда ваше приложение должно генерировать URL-адреса для себя.
String ipAddress = request.getHeader("x-forwarded-for"); if (ipAddress == null) { ipAddress = request.getHeader("X_FORWARDED_FOR"); if (ipAddress == null){ ipAddress = request.getRemoteAddr(); } }
Заголовок запроса «x-forwarded-for» содержит исходный IP-адрес клиента, если используется прокси-сервер или балансировщик нагрузки. Но я думаю, что не все прокси / lb добавляют этот заголовок.
Здесь некоторый Java-код для parsingа заголовка: http://www.codereye.com/2010/01/get-real-ip-from-request-in-java.html
Если этот заголовок отсутствует, я буду продолжать, как @Bozho предлагает
InetAddress inetAddress = InetAddress.getLocalHost(); String ip = inetAddress.getHostAddress();