【问题标题】:When HttpServletRequest getHeader return unknown?当 HttpServletRequest getHeader 返回未知?
【发布时间】:2018-08-13 23:52:57
【问题描述】:

我正在使用以下代码(从另一篇帖子复制 - How do I get the remote address of a client in servlet?)获取客户端 IP 地址以及代理服务器(部署在 PCF 中的 SpringBoot Appln)。

  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(); (从本地运行时)给出预期的结果。实在不明白其他条件的用途。

  1. 在所有情况下,我都看到“未知”。equalsIgnoreCase(IP) 被使用。但是当我尝试访问 request.getHeader("Proxy-Client-IP") 或任何垃圾字符串时,我得到了空值。 当 HttpServletRequest getHeader 返回未知?这可以忽略吗?
  2. Proxy-Client-IP/HTTP_CLIENT_IP 有什么用。我猜它是用来单独获取客户端IP(没有代理服务器IP)的。它是特定于特定服务器的吗?如果是的话,哪个服务器。 这可以在 Spring Boot 应用程序中忽略吗
  3. 我猜“WL-Proxy-Client-IP”是 WebLogic 特有的。这也可以忽略吗?
  4. 我认为 HTTP_ 前缀是 PHP 特有的(HTTP_X_FORWARDED_FOR 和 HTTP_CLIENT_IP。)在 SpringBoot 应用程序中是否有必要?
  5. 我觉得下面的代码足以获取客户端 IP 地址以及代理服务器(前提是我使用带有嵌入式 tomcat 的 spring boot 并将代码部署在 PCF 中)。你能确认一下吗?

    private static String getClientIpAddr(HttpServletRequest httpRequest)
    {
      String clientIp = httpRequest.getHeader("X-Forwarded-For");
    
      if (clientIp == null || clientIp.length() == 0)
      {
        clientIp = httpRequest.getRemoteAddr();
      }
      return clientIp;
    }
    

【问题讨论】:

  • 那么你的做法有什么问题呢?对于您的提议方式和我的快速浏览,这似乎是一个更强大的解决方案,如果设置了X-Forwarded-For,那么结果将是相同的。
  • Sonaqube 抱怨这种方法的圈复杂度大于授权。我可以通过其他方式解决这个问题,但我只是不想有垃圾未使用的代码。此外,它会影响覆盖范围。我只是想确保在删除未使用的代码之前。
  • 我猜 'WL-Proxy-Client-IP' 是特定于 WebLogic 的。这也可以忽略 - 这是你的环境,所以你应该更了解
  • @Thiagarajan Ramanathan,另请参阅stackoverflow.com/questions/18350318/…
  • 只需创建一个标题名称列表来检查,遍历它们,当你回来时使用它。 if 语句中的内容总是相同的。您可能想要做的一个补充是将ip 转换为String[]。当涉及多个路由器时,X-Forwarded-For 可能会成为多个 IP 的逗号分隔列表。其中第一个是你想要的IP。

标签: java spring-boot proxy http-headers clientip


【解决方案1】:

你可能想要这样的东西。

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

这将尝试所有标题(按给定顺序),如果存在则返回。否则它将回退到request.getRemoteAddr()。用更少的if 语句实现相同的效果。

我还考虑了X-Forwarded-For 标头中可能存在多个 IP 地址的情况。它总是返回解析数组中的第一个元素。

【讨论】:

  • 感谢您的回答。但我更感兴趣的是了解“未知”、“Proxy-Client-IP”、“WL-Proxy-Client-IP”、“HTTP_CLIENT_IP”、“HTTP_X_FORWARDED_FOR”的使用。有必要吗?如果 spring boot 代码部署在 PCF 中并通过 Apigee 代理访问,它会增加任何价值吗?
  • 这些可能不会添加任何内容,因为我相信这些是特定于 WebLogic 和 PHP 的。因此,除非您打算使用它们,否则它们不会添加任何内容。 unknown的原因我不知道,你应该问你正在使用的代码的人:)。
猜你喜欢
  • 1970-01-01
  • 2016-02-14
  • 2013-06-14
  • 2018-09-25
  • 2023-01-27
  • 1970-01-01
  • 2014-11-14
  • 2012-02-14
  • 2017-08-04
相关资源
最近更新 更多