How do I get the remote address of a client in servlet?
Asked Answered
C

12

77

Is there any way that I could get the original IP address of the client coming to the server? I can use request.getRemoteAddr(), but I always seem to get the IP of the proxy or the web server.

I would want to know the IP address that the client is using to connect to me. Is there anyway that I could get it?

Cookshop answered 13/1, 2011 at 10:6 Comment(0)
O
120

try this:

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;  
    }  
Onwards answered 10/3, 2013 at 15:16 Comment(3)
Is it OK, in this case, use if conditiona instead of if/else ?Killie
yes because we need to check if the previous operation is succeed or not maybe using do-while would be betterOnwards
X-Forwarded-For can contain more than one IP address.Daloris
V
11

Why don't use a more elegant solution like this?

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

Deduplicate your code!

Viscose answered 18/1, 2019 at 14:45 Comment(0)
O
10

request.getRemoteAddr() is the way. It appears your proxy changes the source IP. When some proxies do that they add the original IP in some custom http header. Use request.getHeaderNames() and request.getHeaders(name) and print all of them to see if there isn't anything of interest. Like X-CLIENT-IP (made that one up, but they look like this)

Osugi answered 13/1, 2011 at 10:8 Comment(2)
thanks, i'll check the headers.... although when it passes through a web server for example, i then get the webserver addressCookshop
Do you mean request.getHeaderNames()?Sollars
C
7

As this is usually a deployment concern, rather than an application concern, another approach would be to configure the application container appropriately. Once configured, the container takes care of inspecting the appropriate header and your application continues to use request.getRemoteAddr().

For example, in Tomcat you can use the Remote IP Valve. I would assume most application servers have similar functionality.

The container could also take care of understanding if your front-end load balancer is terminating SSL connections, forwarding the request to the app server over HTTP. This is important when your application needs to generate URLs to itself.

Countershading answered 14/7, 2014 at 20:30 Comment(0)
C
6

The best solution I've ever used

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;      
} 
Christychristye answered 6/11, 2013 at 7:6 Comment(0)
Z
4

You cannot do this in a meaningful way.

The proxy may or may not add a proxied-for header, but in many cases this will be an internal only address anyway, so it will be meaningless to you. Most proxies at the edge of an organization are configured to reveal as little as possible about the internals of the network anyway.

What are you intending to use this information for?

Zomba answered 13/1, 2011 at 10:24 Comment(2)
well, i'm sort of required to log the address of the users who are accessing. you're right, some proxies seem to remove it and i often have the proxy replacing it.... i was thinking if maybe i could get some information from the SSL sessionCookshop
Nope. The client IP is not passed in the SSL negotiation.Cladoceran
F
1

"x-forwarded-for" request header contains the original client IP if using a proxy or a load balancer. But I think not all proxies/lb adds this header.

Here some java code to parse the header: http://www.codereye.com/2010/01/get-real-ip-from-request-in-java.html

If this header is not present then I would proceed as @Bozho suggests

Frizzell answered 10/7, 2013 at 12:9 Comment(0)
S
0
String ipAddress = request.getHeader("x-forwarded-for");
        if (ipAddress == null) {
            ipAddress = request.getHeader("X_FORWARDED_FOR");
            if (ipAddress == null){
                ipAddress = request.getRemoteAddr();
            }
        }
Sparky answered 6/6, 2013 at 6:12 Comment(0)
A
0

Why I think we should try to get IP from header 'X-Forwarded-For' first? If you get from request.getRemoteAddr(), it could be client's real ip or last proxy's ip which forwards the request. Thus we can't tell which condition it belongs to. However, if 'X-Forwarded-For' is set into the header, client ip is bound to be the left-most part of what you get from it.

    /**
     * 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 "";
    }
Acnode answered 17/4, 2019 at 6:56 Comment(0)
S
0

request.getHeader("True-Client-IP")

it will return the client IP address

Statius answered 16/3, 2021 at 13:51 Comment(0)
A
0

This is the complete solution, Just copy paste and run the code


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 :- Now just try to access your application over the remote client's machine http://IPofMachineWheretheCodeisHosted:PORT/ipaddress you will get the ip address of the remote client

Allmon answered 30/11, 2023 at 8:19 Comment(0)
H
-8
InetAddress inetAddress = InetAddress.getLocalHost();
String ip = inetAddress.getHostAddress();
Hawkinson answered 24/7, 2015 at 6:32 Comment(1)
This just give the localhost's IP.Tabulator

© 2022 - 2024 — McMap. All rights reserved.