java程序里面回去http请求的IP地址的方法是:request.getRemoteAddr(),这种方法在很久很久以前是有效的。但是现在的web服务一般都是经过了nginx、Apache,Squid等反向代理软件做了多级代理,这时候获取的就是最后一级代理服务器的ip,而不是发起http请求的客户端的真实IP地址。
例如:如果使用了nginx将客户访问的http://www.abc.com/转向内网真实的web服务http://192.168.1.110:2046/,用request.getRemoteAddr()方法获取的IP地址是:127.0.0.1或192.168.1.110,而并不是客户端的真实IP。
网上抄了一段代码,加以修改:
public class RequestUtils {
private static final List<String> PROXY_HEADERS = new ArrayList<>();
static {
PROXY_HEADERS.add("x-forwarded-for");
PROXY_HEADERS.add("Proxy-Client-IP");
PROXY_HEADERS.add("WL-Proxy-Client-IP");
PROXY_HEADERS.add("Http_Client_IP");
PROXY_HEADERS.add("X-Real-IP");
}
public static String getClientIP(HttpServletRequest request) {
try {
if (request == null)
return "";
String ip = "";
for (String proxyHeader : PROXY_HEADERS) {
String ipsInHeader = request.getHeader(proxyHeader);
if ((!StringUtils.isBlank(ipsInHeader)) && (!"unknown".equalsIgnoreCase(ipsInHeader))) {
ip = getFistIPInHeader(ipsInHeader);
break;
}
}
if ("".equals(ip)) {
ip = request.getRemoteAddr();
}
return ip;
} catch (RuntimeException e) {
return "";
}
}
private static String getFistIPInHeader(String ipsInHeader) {
String[] ipGroup = ipsInHeader.split(",");
for (String ip : ipGroup) {
if (!"unknown".equalsIgnoreCase(ip)) {
return ip;
}
}
return "";
}
}
其中用到了四个请求头,这些请求头的意思分别是:
比如我们使用nginx做代理,需要在nginx中添加配置:
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Real-IP #remote_addr;
摘抄一段其他人写的注意事项: