【问题标题】:How do I get the remote address of a client in servlet?如何在 servlet 中获取客户端的远程地址?
【发布时间】:2011-06-08 09:44:33
【问题描述】:

有什么方法可以让客户端的原始 IP 地址进入服务器? 我可以使用request.getRemoteAddr(),但我似乎总是获得代理或网络服务器的IP。

我想知道客户端用来连接我的 IP 地址。反正我能得到它吗?

【问题讨论】:

    标签: servlets proxy client ip-address


    【解决方案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;  
        }  
    

    【讨论】:

    • 可以吗,这种情况下,用if conditiona代替if/else?
    • 是的,因为我们需要检查之前的操作是否成功,也许使用do-while会更好
    • X-Forwarded-For 可以包含多个 IP 地址。
    【解决方案2】:

    request.getRemoteAddr() 就是这样。您的代理似乎更改了源 IP。当一些代理这样做时,他们会在一些自定义 http 标头中添加原始 IP。使用request.getHeaderNames()request.getHeaders(name) 并打印所有这些以查看是否有任何感兴趣的内容。喜欢X-CLIENT-IP(做了一个,但它们看起来像这样)

    【讨论】:

    • 谢谢,我会检查标题....尽管例如当它通过网络服务器时,我会得到网络服务器地址
    • 你的意思是 request.getHeaderNames() 吗?
    【解决方案3】:

    由于这通常是部署问题,而不是应用程序问题,另一种方法是适当地配置应用程序容器。配置完成后,容器会负责检查相应的标头,并且您的应用程序会继续使用 request.getRemoteAddr()

    例如,在 Tomcat 中,您可以使用 Remote IP Valve。我会假设大多数应用服务器都有类似的功能。

    容器还可以负责了解您的前端负载平衡器是否正在终止 SSL 连接,并通过 HTTP 将请求转发到应用服务器。当您的应用程序需要为其自身生成 URL 时,这一点很重要。

    【讨论】:

      【解决方案4】:

      我用过的最好的解决方案

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

      【讨论】:

        【解决方案5】:

        为什么不使用这样更优雅的解决方案?

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

        对您的代码进行重复数据删除!

        【讨论】:

          【解决方案6】:

          你不能以有意义的方式做到这一点。

          代理可能会或可能不会添加代理标头,但在许多情况下,无论如何这将是一个仅限内部的地址,因此对您来说毫无意义。无论如何,组织边缘的大多数代理都被配置为尽可能少地透露网络内部信息。

          您打算将这些信息用于什么目的?

          【讨论】:

          • 好吧,我有点需要记录正在访问的用户的地址。你是对的,一些代理似乎删除了它,我经常让代理替换它....我在想我是否可以从 SSL 会话中获取一些信息
          【解决方案7】:

          “x-forwarded-for”请求标头包含原始客户端 IP(如果使用代理或负载平衡器)。但我认为并非所有代理/磅都添加此标头。

          这里有一些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】:

              为什么我认为我们应该首先尝试从标头“X-Forwarded-For”获取 IP?如果您来自request.getRemoteAddr(),则可能是client's real ip or last proxy's ip which forwards the request。因此我们无法判断它属于哪个条件。但是,如果 '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】:

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

                它将返回客户端IP地址

                【讨论】:

                  【解决方案11】:
                  InetAddress inetAddress = InetAddress.getLocalHost();
                  String ip = inetAddress.getHostAddress();
                  

                  【讨论】:

                  • 这只是给出本地主机的IP。
                  猜你喜欢
                  • 2016-09-25
                  • 2012-06-06
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  • 2018-04-30
                  • 2023-04-02
                  • 2012-05-10
                  相关资源
                  最近更新 更多