简介
- 获取客户端的IP地址常用的方法是:request.getRemoteAddr()。但是如果通过了Apache,Nagix等反向代理软件则获取不到客户端的真实IP。
- 经过代理以后,由于在客户端和服务之间增加了中间层,因此服务器无法直接拿到客户端的IP,服务器端应用也无法直接通过转发请求的地址返回给客户端。但是在转发请求的HTTP头信息中,增加了X-FORWARDED-FOR信息。用以跟踪原有的客户端IP地址和原来客户端请求的服务器地址。
- 例如:使用反向代理,将http://192.168.10.1:8081的URL反向代理为http://example.com时,用 request.getRemoteAddr() 方法获取的IP地址是:127.0.0.1或192.168.10.1,而并不是客户端的真实IP。也就是说访问http://example.com,是经过代理服务器访问http://192.168.10.1:8081的,因此request.getRemoteAddr()获取的IP其实是代理服务器的IP。
获取方法
(1)方法一
public String getRemortIP(HttpServletRequest request) {
if (request.getHeader("x-forwarded-for") == null) {
return request.getRemoteAddr();
}
return request.getHeader("x-forwarded-for");
}
(2)方法二:squid.conf 的配制文件 forwarded_for 项默认是为on,如果 forwarded_for 设成了 off 则:X-Forwarded-For: unknown
//equalsIgnoreCase将字符串与指定的对象比较,不考虑大小写。
//isBlank 字符串为空、长度为0或由空白符组成
public String getIpAddr(HttpServletRequest request) {
String[] headers = ["x-forwarded-for","Proxy-Client-IP","WL-Proxy-Client-IP"]
String ip = null;
for(String header: headers){
if(StringUtils.isBlank(addr) || "unknown".equalsIgnoreCase(ip)) {
ip = request.getHeader(header);
}
}
if(StringUtils.isBlank(addr) || "unknown".equalsIgnoreCase(ip)) {
ip = request.getRemoteAddr();
}
return ip;
}
(3)如果使用多级反向代理,X-Forwarded-For的值并不止一个,获取到的是一串IP值。
public static String getClientIP(HttpServletRequest request) {
String[] headers = {"x-forwarded-for","Proxy-Client-IP","WL-Proxy-Client-IP"};
String ip = null;
for(String header: headers){
if(StringUtils.isBlank(ip) || "unknown".equalsIgnoreCase(ip)) {
ip = request.getHeader(header);
}
}
if(StringUtils.isBlank(ip) || "unknown".equalsIgnoreCase(ip)) {
ip = request.getRemoteAddr();
if(ip.equals("127.0.0.1") || ip.equals("0:0:0:0:0:0:0:1")){
//根据网卡取本机配置的IP
InetAddress inet=null;
try {
inet = InetAddress.getLocalHost();
} catch (UnknownHostException e) {
e.printStackTrace();
}
ip= inet.getHostAddress();
}
}
//if(ip.contains(","){
if(StringUtils.isBlank(ip)){
if(ip.indexOf(",")>0){
ip= ip.substring(0,ip.indexOf(","));
}
}
return ip;
}