获取请求的IP地址正确方法是什么?

31

我在servlet中发现了一些不同的获取IP地址的方法,但我不知道哪个是正确的以及为什么。

1:

request.getHeader( "X-Real-IP" )

2:

  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();  
    } `
 String ip=request.getHeader("x-forwarded-for");
                if(ip==null){
                    ip=request.getRemoteAddr();
                }
                String ips[]=ip.split(",");`
                                ip=ips[0];

请查看此链接:https://dev59.com/rWkv5IYBdhLWcg3wwjkI#10363109 - user784540
2个回答

65
答案比较复杂。
  • 如果您的Servlet运行在一个Web服务器后面的反向代理或负载均衡器上,那么这个Web代理可以配置成插入一个请求头来给出请求来自哪个IP地址。不同的反向代理会插入不同的头文件,请参考您(前端)服务器的文档。

  • 如果您的客户端使用一个正向代理,那么它可能会插入头部来说明客户端的IP地址。。或者也可能不插入。而且插入的IP地址可能是不正确的。

  • 通过调用request.getRemoteAddr()得到的值将是请求的直接上游源的IP地址。

您列出的头文件都不是标准的,但是“x-forwarded-for”被认为是事实上的标准;即如果有任何东西被插入,它是最有可能被一个代理等插入的。

最后,即使您获得了一个IP地址,也不一定有帮助。例如,如果客户端位于私有网络上,并通过NAT网关连接到互联网,则HTTP请求中的IP地址将是NAT服务器的地址...而不是实际的客户端IP。


所以这意味着什么?基本上,这意味着通常您无法可靠地找出请求来源系统的IP地址。


1
非常感谢您的出色回答,我们使用nginx+tomcat+spring+spring mvc+mybatis。我在中国,这是我在StackOverflow上的第二个问题,我的第一个问题失败了--!我认为我们应该对它进行更多的测试。 - sprite
1
@sprite - 你应该查阅 Nginx 文档,找出它使用的头部是什么。但这只会给你上游主机的 IP 地址 ... 可能不是真实客户端的地址。就像我说的,你不能总是获取到真实的客户端 IP ... 即使你可以,它也不一定可靠、有用或唯一。 - Stephen C
1
好的,我差不多理解了你的建议。"下一个上游主机的IP地址"是指最后一个代理的IP地址吗?@Stephen C - sprite
1
@sprite - 是的。那是网络层唯一可用的IP地址。(而且想想看,你不能完全依赖于那个IP地址的真实性...因为IP地址可以被欺骗。) - Stephen C

21

这似乎是我们能够获取客户端原始IP地址的最佳方法。

String ipAddress = request.getHeader("X-FORWARDED-FOR");  
if (ipAddress == null) {  
   ipAddress = request.getRemoteAddr();  
}

6
除非它不起作用;请参考我的回答。 - Stephen C
11
由于X-Forwarded-For可以包含逗号分隔的(可选有空格)代理IP地址列表,因此这不起作用! - Yeti
它可以,但正如其他答案已经指出的那样,其价值完全取决于您的代理配置,在这种情况下,您将覆盖任何此类上游头作为安全预防措施,因为它们是不可信的。 - Morten Haraldsen

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接