记一次Nginx配置错误,Java获取不到IP地址的经历
Java获取IP地址
在JSP里,获取客户端的IP地址的方法是:request.getRemoteAddr(),这种方法在大部分情况下都是有效的。
是在通过了Apache,Squid等反向代理软件就不能获取到客户端的真实IP地址了。
经过代理以后,由于在客户端和服务之间增加了中间层,因此服务器无法直接拿到客户端的 IP,服务器端应用也无法直接通过转发请求的地址返回给客户端。但是在转发请求的HTTP头信息中,增加了X-FORWARDED-FOR信息。用以跟踪原有的客户端IP地址和原来客户端请求的服务器地址。
方法1
/**
* 获取当前网络ip
* @param request
* @return
*/
public String getIpAddr(HttpServletRequest request){
String ipAddress = request.getHeader("x-forwarded-for");
if(ipAddress==null||ipAddress.length()== 0||"unknown".equalsIgnoreCase(ipAddress)){
ipAddress=request.getHeader("Proxy-Client-IP");
}
if(ipAddress==null||ipAddress.length()== 0||"unknown".equalsIgnoreCase(ipAddress)){
ipAddress = request.getHeader("WL-Proxy-Client-IP");
}
if(ipAddress==null||ipAddress.length()== 0||"unknown".equalsIgnoreCase(ipAddress)){
ipAddress = request.getRemoteAddr();
if(ipAddress.equals("127.0.0.1") || ipAddress.equals("0:0:0:0:0:0:0:1")){
/*根据网卡取本机配置的IP */
InetAddress inet=null;
try {
inet = InetAddress.getLocalHost();
} catch (UnknownHostException e) {
e.printStackTrace();
}
ipAddress= inet.getHostAddress();
}
}
/*对于通过多个代理的情况,第一个IP为客户端真实IP,多个IP按照','分割 */
if(ipAddress!=null && ipAddress.length()>15){ /*"***.***.***.***".length() = 15*/
if(ipAddress.indexOf(",")>0){
ipAddress = ipAddress.substring(0,ipAddress.indexOf(","));
}
}
return ipAddress;
}
方法2
package com.lzhpo.utils;
import org.springframework.util.StringUtils;
import javax.servlet.http.HttpServletRequest;
/**
* 获取IP的工具类
*
* @author lzhpo
* @version 1.0
* @website http://www.lzhpo.com
* @date 2018/4/18 11:48
* @since 1.0
*/
public class IpUtil {
/**
* 获取真实IP
*
* @param request
* @return
*/
public static String getRealIp(HttpServletRequest request) {
String ip = request.getHeader("x-forwarded-for");
return checkIp(ip) ? ip : (
checkIp(ip = request.getHeader("Proxy-Client-IP")) ? ip : (
checkIp(ip = request.getHeader("WL-Proxy-Client-IP")) ? ip :
request.getRemoteAddr()));
}
/**
* 校验IP
*
* @param ip
* @return
*/
private static boolean checkIp(String ip) {
return !StringUtils.isEmpty(ip) && !"unknown".equalsIgnoreCase(ip);
}
}
方法3
简单粗暴。
public String getRemortIP(HttpServletRequest request) {
if (request.getHeader("x-forwarded-for") == null) {
return request.getRemoteAddr();
}
return request.getHeader("x-forwarded-for");
}
But
这两种方式其实都是一样的,只是方法2封装的好看一点。
我配置的Nginx都是获取不到用户真实IP。
比如:我访问我的博客www.lzhpo.com,我使用了代理工具Nginx,访问过程如下:
www.lzhpo.com => 我的服务器IP地址 => 获取用户访问的真实IP
所以,如果是直接是在我域名的情况下获取的IP是我的服务器的IP,而不是真实用户的IP,因为我Nginx以及反向代理到了我的服务器IP。
配置Nginx,还是拿我的博客www.lzhpo.com为例:
server {
listen 80;
server_name www.lzhpo.com;
location / {
proxy_pass http://47.106.236.228:8443;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
}
意思是增加一个$proxy_add_x_forwarded_for到X-Forwarded-For里去,注意是增加,而不是覆盖,当然由于默认的X-Forwarded-For值是空的,所以我们总感觉X-Forwarded-For的值就等于$proxy_add_x_forwarded_for的值,实际上当你搭建两台nginx在不同的ip上,并且都使用了这段配置,那你会发现在web服务器端通过request.getAttribute("X-Forwarded-For")获得的将会是客户端ip和第一台nginx的ip。
我就是因为没加上proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
导致获取不到用户访问的IP地址,无法定位。
那么$proxy_add_x_forwarded_for又是什么?
$proxy_add_x_forwarded_for变量包含客户端请求头中的"X-Forwarded-For",与$remote_addr两部分,他们之间用逗号分开。
题外话
配合百度地图开放平台)食用,效果更佳~
- 本文标签: Nginx Java
- 本文链接: http://www.lzhpo.com/article/71
- 版权声明: 本文由lzhpo原创发布,转载请遵循《署名-非商业性使用-相同方式共享 4.0 国际 (CC BY-NC-SA 4.0)》许可协议授权