public class IPUtil { public static String getIpAddress(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.equals("0:0:0:0:0:0:0:1") ? "127.0.0.1" : ip.split(",")[0]; } }
通常服务器中都会对request对象进行再包装java
X-Forwarded-Fornginx
这是一个 Squid 开发的字段,只有在经过了 HTTP 代理或者负载均衡服务器时才会添加该项。格式为X-Forwarded-For: client1, proxy1, proxy2,通常状况下,第一个ip为客户端真实ip,后面的为通过的代理服务器ip。如今大部分的代理都会加上这个请求头web
Proxy-Client-IP/WL- Proxy-Client-IPapache
这个通常是通过apache http服务器的请求才会有,用apache http作代理时通常会加上Proxy-Client-IP请求头,而WL- Proxy-Client-IP是他的weblogic插件加上的头服务器
HTTP_CLIENT_IP网络
有些代理服务器会加上此请求头架构
X-Real-IP负载均衡
nginx代理通常会加上此请求头。tcp
有几点要注意ui
一、这些请求头都不是http协议里的标准请求头,也就是说这个是各个代理服务器本身规定的表示客户端地址的请求头。若是哪天有一个代理服务器软件用oooo-client-ip这个请求头表明客户端请求,那上面的代码就不行了。
二、这些请求头不是代理服务器必定会带上的,网络上的不少匿名代理就没有这些请求头,因此获取到的客户端ip不必定是真实的客户端ip。代理服务器通常均可以自定义请求头设置。
三、即便请求通过的代理都会按本身的规范附上代理请求头,上面的代码也不能确保得到的必定是客户端ip。不一样的网络架构,判断请求头的顺序是不同的。
四、最重要的一点,请求头都是能够伪造的。若是一些对客户端校验较严格的应用(好比投票)要获取客户端ip,应该直接使用ip = request.getRemoteAddr (),虽然获取到的多是代理的ip而不是客户端的ip,但这个获取到的ip基本上是不可能伪造的,也就杜绝了刷票的可能。(有分析说arp欺骗+syn有可能伪造此ip,若是真的能够,这是全部基于TCP协议都存在的漏洞),这个ip是tcp链接里的ip。