java http获取真实ip 防止伪造ip

先说下各个常用请求头.

X-Real-IP 是Nginx的反向代理标志(只包含真实ip)

x-forwarded-for 是Nginx的反向代理标志(包含真实ip和反向代理服务器地址,以“,”隔开,第一个为用户真实ip,后面的是各个层代理服务器ip)

Proxy-Client-IP 是Apache的反向代理标志

WL-Proxy-Client-IP 是WebLogic的反向代理标志

下面看下常用的获取ip方法,如下所示:

public static 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;

}

 

上面的方法在测试过程中是能获取到真实ip的,但是前提是用户没有进行伪造。

现在来分析下用户是如何进行伪造请求头。

 

情况1:  服务器使用的是Apache(Proxy-Client-IP请求头)或者是WebLogic(WL-Proxy-Client-IP请求头)反向代理,或者没有使用反向代理

这种情况下,用户可以伪造x-forwarded-for,由于服务器未使用Nginx反向代理,所以不会构造x-forwarded-for,但是用户却伪造了x-forwarded-for,导致在服务器先执行request.getHeader("x-forwarded-for");,所以获取到的ip是用户伪造的。

 

情况2:服务器使用的是WebLogic(WL-Proxy-Client-IP请求头)反向代理,或者没有使用反向代理。

用户可以伪造x-forwarded-for或Proxy-Client-IP请求头,此时服务器获取的是用户的伪造ip。

 

情况3:服务器没有使用反向代理。

用户可以伪造x-forwarded-for或Proxy-Client-IP或WL-Proxy-Client-IP请求头,此时服务器获取的是用户的伪造ip。

 

情况4:服务器使用的是Nginx(x-forwarded-for 请求头)反向代理。

这种情况下可能大家会人为是没问题的,但如果不配置好Nginx,也会获取到伪造的ip。

比如Nginx的配置是proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

这个配置是对x-forwarded-for请求头进行追加ip。如果用户伪造x-forwarded-for请求头的话,Nginx不会覆盖用户伪造的ip,而是追加到后面,这样获取的也是伪造的ip。

解决方法:

 

1):未使用反向代理情况下:

未使用反向代理下,不需要从请求头去获取用户ip,用request.getRemoteAddr();方法就能获取到用户的ip了。

 

2):使用Nginx反向代理情况,代码如下:

public static String getIpAddr(HttpServletRequest request) throws UnknownHostException {



// 从Nginx中X-Real-IP获取真实ip

String ipAddress = request.getHeader("X-Real-IP");



if (ipAddress != null && ipAddress.length() > 0 && !"unknown".equalsIgnoreCase(ipAddress)) {

logger.info("从X-Real-IP中获取到ip:" + ipAddress);

return ipAddress;

}



// 从Nginx中x-forwarded-for获取真实ip

ipAddress = request.getHeader("x-forwarded-for");



if (ipAddress != null && ipAddress.length() > 0 && !"unknown".equalsIgnoreCase(ipAddress)) {

// 对于通过多个代理的情况,第一个IP为客户端真实IP,多个IP按照','分割

int index = ipAddress.indexOf(",");

if (index > 0) {

ipAddress = ipAddress.substring(0, ipAddress.indexOf(","));

}

logger.info("从x-forwarded-for中获取到ip:" + ipAddress);

return ipAddress;

}



ipAddress = request.getRemoteAddr();

if ("127.0.0.1".equals(ipAddress) || "0:0:0:0:0:0:0:1".equals(ipAddress)) {

// 根据网卡取本机配置的IP

ipAddress = InetAddress.getLocalHost().getHostAddress();

}

logger.info("从request.getRemoteAddr()中获取到ip:" + ipAddress);

return ipAddress;



}

 

以上是获取ip代码,另外Nginx还需要配置正确,如果Nginx反向代理有多台,那么在最外层的反向代理服务器加上

proxy_set_header X-Real-IP $remote_addr;

proxy_set_header X-Forwarded-For $remote_addr;

内层的反向代理服务器加上

proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

(!注意不要加X-Real-IP配置)

配置好后重启Nginx即可

这样java中获取的ip就是真实的ip了(不考虑用户使用代理或者VPN),即使用户伪造请求头,我们获取到的仍然是真实ip。如果Nginx不想配置X-Real-IP,那么也要删除掉java中对应的获取X-Real-IP代码

来源: http://blog.sina.com.cn/s/blog_13785e1370102x8n9.html

  • 0
    点赞
  • 18
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值