-1

I am using the below code (Copied from another post - How do I get the remote address of a client in servlet?) to get the client IP address along with the proxy server (SpringBoot Appln deployed in PCF).

  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.getHeader("X-Forwarded-For"); /request.getRemoteAddr(); (when run from local) gives the expected result. I really didn't understand the uses of other conditions.

  1. In all conditions I see "unknown".equalsIgnoreCase(IP) is used. But when I try to access request.getHeader("Proxy-Client-IP") or any junk string, I am getting null. When HttpServletRequest getHeader return unknown? Can this be ignored?
  2. What is the use of Proxy-Client-IP/HTTP_CLIENT_IP. I guess it is used to get client IP alone (without proxy server IP). Is it specific to a particular server? if so which server. Can this be ignored in Spring boot application
  3. I guess 'WL-Proxy-Client-IP' is specific to WebLogic. Can this be ignored as well?
  4. I believe the HTTP_ prefix is specific to PHP (HTTP_X_FORWARDED_FOR and HTTP_CLIENT_IP.) Is it necessary in the SpringBoot application?
  5. I feel the below code is more than enough to get the client IP address along with the proxy server (provided I use spring boot with embedded tomcat and deploy the code in PCF). Could you please confirm?

    private static String getClientIpAddr(HttpServletRequest httpRequest)
    {
      String clientIp = httpRequest.getHeader("X-Forwarded-For");
    
      if (clientIp == null || clientIp.length() == 0)
      {
        clientIp = httpRequest.getRemoteAddr();
      }
      return clientIp;
    }
    
Thiagarajan Ramanathan
  • 1,035
  • 5
  • 24
  • 32
  • so what is the problem with the way that you are doing it? It seems a more robust solution to how you are proposing and to my quick glance, if `X-Forwarded-For` is set then the result would be the same. – Scary Wombat Aug 13 '18 at 23:57
  • Sonaqube is complaining that the Cyclomatic Complexity of this method is greater than authorized. I can fix the issue by other ways but I just don't want to have junk unused code. Also, It affects cover coverage. I just want to make sure before deleting the un used code. – Thiagarajan Ramanathan Aug 14 '18 at 00:04
  • *I guess 'WL-Proxy-Client-IP' is specific to WebLogic. Can this be ignored as well* - it is your environment so you should know better – Scary Wombat Aug 14 '18 at 00:10
  • @Thiagarajan Ramanathan, please also see https://stackoverflow.com/questions/18350318/what-is-the-right-way-to-get-requests-ip – John Aug 14 '18 at 01:50
  • Just create a list of header names to check, iterate through them and when one comes back use that. The stuff inside the `if` statements is always the same. One addition you might want to do is convert the `ip` to a `String[]`. potentially when multiple routers are involved the `X-Forwarded-For` becomes a comma separated list of multiple IPs. Where the first one is the IP you want. – M. Deinum Aug 14 '18 at 06:58

1 Answers1

1

You probably want something like this.

public class HttpRequestHelper {

    private static final String[] HEADERS= {"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 header : HEADERS) {
            String ip = request.getHeader(header);
            if (ip != null && ip.length() > 0) {                    
                return StringUtils.commaDelimitedListToStringArray(ip)[0];
            }
        }
        return request.getRemoteAddr();
    }    
}

This will try al headers (in the given order) and if one exists return that. Else it will fallback to the request.getRemoteAddr(). Achieves the same with a lot less if statements.

I also factored in the case for potential multiple ip-addresses in the X-Forwarded-For header. It will always return the first element in the parsed array.

M. Deinum
  • 115,695
  • 22
  • 220
  • 224
  • Thank you for the answer. But I am more interested understanding the use of "unknown","Proxy-Client-IP", "WL-Proxy-Client-IP", "HTTP_CLIENT_IP", "HTTP_X_FORWARDED_FOR". Is it necessary? Will it add any value if the spring boot code is deployed in PCF and accessed via Apigee proxy? – Thiagarajan Ramanathan Aug 14 '18 at 14:49
  • Those will probably not add anything as those are specific for WebLogic and PHP I believe. So unless you intend to use them they don't add anything. The reason for `unknown` I don't know, you should ask that the person who's code you are using :). – M. Deinum Aug 15 '18 at 05:13