Как получить удаленный адрес клиента в сервлет?
Есть ли способ получить исходный IP-адрес клиента, поступающего на сервер?
Я могу использовать request.getRemoteAddr()
, но я всегда получаю IP-адрес прокси-сервера или веб-сервера.
Я хотел бы узнать IP-адрес, который клиент использует для подключения ко мне. Есть ли в любом случае, что я мог бы получить его?
Ответы
Ответ 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();