常见的问题,记录操作日志中发现,getRemoteAddr取到的客户端的ip地址不是真实的ip,需要解析请求头中的信息获取正确ip。
public static String getIpAddress(HttpServletRequest request) { String ip = request.getHeader("X-Forwarded-For"); if (ip == null || ip.length() == 0 || UNKNOWN.equalsIgnoreCase(ip)) { 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.getHeader("X-Real-IP"); } if (ip == null || ip.length() == 0 || UNKNOWN.equalsIgnoreCase(ip)) { ip = request.getRemoteAddr(); } } else { String[] ips = ip.split(","); for (int index = 0; index < ips.length; index++) { String strIp = ips[index]; if (!(UNKNOWN.equalsIgnoreCase(strIp))) { ip = strIp; break; } } } return ip; }
查了下,对应的header头解释如下。
x-forwarded-for只是代理的其中一种,最早Squid 引入,还有很多其他的字段
Proxy-Client-IP:使用apache代理
WL-Proxy-Client-IP:使用weblogic时
HTTP_CLIENT_IP和HTTP_X_FORWARDED_FOR:有一些代理
X-Real-IP:Nginx代理
如果通过了多级反向代理的话,X-Forwarded-For的值并不止一个,而是一串Ip值,取X-Forwarded-For中第一个非unknown的有效IP字符串。
每经过一个代理做一次转发,x_forwarded_for就会在后面追加一个代理IP,并且以转发顺序排序。