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

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

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

12 ответов

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

Почему я думаю, что мы должны попытаться получить 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 "";
    }
String ipAddress = request.getHeader("x-forwarded-for");
        if (ipAddress == null) {
            ipAddress = request.getHeader("X_FORWARDED_FOR");
            if (ipAddress == null){
                ipAddress = request.getRemoteAddr();
            }
        }

request.getHeader("Истинный IP-адрес клиента")

он вернет IP-адрес клиента

Это полное решение. Просто скопируйте и запустите код.

      
import java.io.IOException;
import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import org.w3c.dom.Document;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;

@WebServlet("/ipaddress")
public class GetIpAddressServlet extends HttpServlet {
    
    /**
     * Author : Deepak Bajaj
     */

    public static final long serialVersionUID = 1L;

    // Below code is just to get the VALID IP Address headers
    public static final String[] VALID_IP_HEADER_CANDIDATES = { 
            "X-Forwarded-For",
            "Proxy-Client-IP",
            "WL-Proxy-Client-IP",
            "HTTP_X_FORWARDED_FOR",
            "HTTP_X_FORWARDED",
            "HTTP_X_CLUSTER_CLIENT_IP",
            "HTTP_CLIENT_IP",
            "HTTP_FORWARDED_FOR",
            "HTTP_FORWARDED",
            "HTTP_VIA",
            "REMOTE_ADDR" };

    // To get the client's IP Address
    
    public static String GetIpAddressServlet(HttpServletRequest request) throws IOException, ServletException {
        
        for (String header : VALID_IP_HEADER_CANDIDATES) {
            String ip = request.getHeader(header);
            if (ip != null && ip.length() != 0 && !"unknown".equalsIgnoreCase(ip)) {
            }
        }
        return request.getRemoteAddr();
    }
    protected void doGet(HttpServletRequest request, HttpServletResponse response)
            throws ServletException, IOException {

        // Get the client's IP address
        String clientIP = GetIpAddressServlet(request);

        // Print or use the client's IP address as needed
        System.out.println("Client IP Address: " + clientIP);

        // You can send the IP address as a response to the client if needed
        response.getWriter().write("Client IP Address: " + clientIP);
    }

NOTE :- Теперь просто попробуйте получить доступ к вашему приложению через компьютер удаленного клиента http://IPofMachineWheretheCodeisHosted:PORT/ipaddress, вы получите IP-адрес удаленного клиента.

InetAddress inetAddress = InetAddress.getLocalHost();
String ip = inetAddress.getHostAddress();
Другие вопросы по тегам