我们真的能通过请求来获取用户真实的ip地址嘛?
答案是不能,如果能,肯定是我学的不够深入,欢迎交流指正。
那么写这篇文章的意义是什么?我们接着往下看。
IP地址相当于电脑在网络上的身份证,但事实上IP地址却没有想象中那么简单,IP也分很多种,比如经常提到内网IP和外网IP。
外网ip和内网ip的区别是什么?
我自己也对这个是比较模糊的,我就按照自己的理解大概解释一遍。但是我讲的不一定是对的。
我家里的路由器是电信的,路由器上面连接一根电信的电话线,这跟电话线是要我家去电信缴费,才能上网。我家路由器能上网之后,就能打开wifi,我的其他设备就能通过wifi连接上这台路由器。
上面介绍了个大概,接下来说说java端如何获取访问者 IP ?,先上代码
@Slf4j public class IpUtil { /** * 获取用户ip地址 * * @param request 请求 * @return ip地址 */ public static String getIpAddr(HttpServletRequest request) { String ipAddress = request.getHeader("X-Original-Forwarded-For"); log.info("X-Original-Forwarded-For:获取的ipAddress{}",ipAddress); if (ipAddress == null || ipAddress.length() == 0 || "unknown".equalsIgnoreCase(ipAddress)) { ipAddress = request.getHeader("X-Forwarded-For"); log.info("X-Forwarded-For:获取的ipAddress{}",ipAddress); } // 对于通过多个代理的情况,因为ip长度最大为15,如果超过了15就代表有1个以上的ip,这时我们就取第一个,多个IP按照','分割 if (ipAddress != null && ipAddress.length() > 15) { log.info("多个ip情况:获取的ipAddress:{}",ipAddress); if (ipAddress.indexOf(",") > 0) { ipAddress = ipAddress.substring(0, ipAddress.indexOf(",")); } } if (ipAddress == null || ipAddress.length() == 0 || "unknown".equalsIgnoreCase(ipAddress)) { // apache http服务器的请求 ipAddress = request.getHeader("Proxy-Client-IP"); log.info("Proxy-Client-IP:获取的ipAddress{}",ipAddress); } if (ipAddress == null || ipAddress.length() == 0 || "unknown".equalsIgnoreCase(ipAddress)) { // apache http服务器的请求,使用weblogic插件加上的头 ipAddress = request.getHeader("WL-Proxy-Client-IP"); log.info("WL-Proxy-Client-IP:获取的ipAddress{}",ipAddress); } if (ipAddress == null || ipAddress.length() == 0 || "unknown".equalsIgnoreCase(ipAddress)) { // 有些代理服务器会加上此请求头 ipAddress = request.getHeader("HTTP_CLIENT_IP"); log.info("HTTP_CLIENT_IP:获取的ipAddress{}",ipAddress); } if (ipAddress == null || ipAddress.length() == 0 || "unknown".equalsIgnoreCase(ipAddress)) { ipAddress = request.getHeader("HTTP_X_FORWARDED_FOR"); log.info("HTTP_X_FORWARDED_FOR:获取的ipAddress{}",ipAddress); } if (ipAddress == null || ipAddress.length() == 0 || "unknown".equalsIgnoreCase(ipAddress)) { // nginx代理服务器会加上此请求头 ipAddress = request.getHeader("X-Real-IP"); log.info("X-Real-IP:获取的ipAddress{}",ipAddress); } // 没有使用代理的情况 if (ipAddress == null || ipAddress.length() == 0 || "unknown".equalsIgnoreCase(ipAddress)) { ipAddress = request.getRemoteAddr(); log.info("request.getRemoteAddr()------->{}",ipAddress); } // 如果用localhost来访问会返回0:0:0:0:0:0:0:1,这里我们将它转换为127.0.0.1 return "0:0:0:0:0:0:0:1".equals(ipAddress)?"127.0.0.1":ipAddress; } }
这段代码看起来很长,其实有用的部分就是 request.getRemoteAddr();
X-Original-Forwarded-For
Proxy-Client-IP
HTTP_CLIENT_IP
HTTP_X_FORWARDED_FOR
这些都是一些常用的,因为这个请求头类型是可以自定义的,所以我们根据请求头类型获取ip地址是不现实的。
但是为什么代码里面要写呢?人情世故嘛,万一公司是按代码行数算工资的呢。哈哈,开个玩笑,已知的代理请求头,我们还是需要写上去的。
不结合客户使用场景的光讨论技术都是耍流氓。下面我们重点说一下使用场景。
1、上面那段代码部署在外网环境,那么获取到的就是外网的ip,要是别人没有经过伪装,恭喜你,成功拿到他的ip。要是别人特意伪装,你拿到这个ip或许是假的,没有任何意义。
2、上面那段代码部署在内网环境,那么获取到的就是内网ip,这个内网ip,就能查出具体某台电脑,也能在内网中远程控制你的电脑。
上面两个场景都是人畜无害。
一般是第二种情况使用的多。
比如你的公司有20层,公司所有员工都是用内网,你在20楼,你的同事在1楼,恰好你们公司没有电梯,此时你想控制他的电脑,帮她处理一些事情,你就可以让她直接访问那段代码,获取到她的ip地址。当然,代码肯定是封装成一个接口,不然妹子怎么访问。
什么?远程不用向日葵?TV?QQ?
什么?直接叫妹子从电脑查看ip地址发给我?
哈哈,是我格局小了。我就怕妹子不会看啊。
难不成让她自己百度怎么查看ip地址?老实说,有这种想法的是不是还单身?
好了,对于获取ip地址,网上也是各种形形色色,但是要明确使用场景,如果你真的想通过一个ip地址去追寻到一个人或者一台电脑,在公网环境下,有点不现实。但是在内网环境中,这个确实可行。