欢迎来到Java的奇妙世界,一个充满代码、笑声和一点点魔法的地方!今天,我们将一起踏上一场探寻客户端IP地址的欢快旅程。戴上你的思维帽,拿起你的编程魔杖,让我们开启这场充满乐趣的冒险!
1、神奇而古怪的工具类
首先,让我们迎接我们的主角------IpUtil
,一个有着超能力的Java类,它比侦探福尔摩斯还要厉害!它能在一堆复杂的HTTP请求中找到IP
地址,就像是在沙滩上找到那颗特别的沙粒。
java
public class IpUtil {
/**
* @description: 获取客户端的IP地址
* @author: lizhiwei
* @param request
* @return IP地址字符串
* @date: 2024/1/8 10:26
**/
public static String getClientIp(HttpServletRequest request) {
// 尝试从HTTP请求的"X-Forwarded-For"头部获取IP地址。
// "X-Forwarded-For"头通常由代理服务器设置,包含了原始请求的IP地址。
String ip = request.getHeader("X-Forwarded-For");
if (ip != null) {
// 如果"X-Forwarded-For"头包含多个IP地址(通常由于多级代理造成),则取第一个非未知的IP地址。
ip = ip.split(",")[0].trim();
} else {
// 如果"X-Forwarded-For"头不存在,尝试从"Proxy-Client-IP"头获取IP地址。
// "Proxy-Client-IP"头也是由某些代理服务器设置的。
ip = request.getHeader("Proxy-Client-IP");
}
if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
// 如果"Proxy-Client-IP"头不可用,尝试从"WL-Proxy-Client-IP"头获取IP地址。
// "WL-Proxy-Client-IP"是WebLogic服务器设置的类似头部。
ip = request.getHeader("WL-Proxy-Client-IP");
}
if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
// 如果"WL-Proxy-Client-IP"头也不可用,尝试从"X-Real-IP"头获取IP地址。
// "X-Real-IP"头通常被用来记录原始的客户端IP地址。
ip = request.getHeader("X-Real-IP");
}
if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
// 如果以上所有方法都失败,使用request.getRemoteAddr()获取发起请求的客户端IP地址。
// 这通常是直接连接到服务器的客户端IP。
ip = request.getRemoteAddr();
if ("127.0.0.1".equals(ip) || "0:0:0:0:0:0:0:1".equals(ip)) {
// 如果获取到的IP是本地回环地址,尝试获取本机的真实IP地址。
try {
ip = InetAddress.getLocalHost().getHostAddress();
} catch (UnknownHostException e) {
// 如果本机IP地址获取失败,将IP地址设置为"unknown"。
ip = "unknown";
}
}
}
return ip; // 返回获取到的IP地址。
}
}
2、勇敢的控制器
但是,哪怕是最伟大的侦探也需要一个可靠的助手。在我们的故事里,这个角色由controller
扮演。他就像是魔法界的电话接线员,一旦有人需要寻找IP,他就迅速将呼叫转给我们的超级侦探IpUtil
。
java
@GetMapping("/getUserIp")
public BaseResponse<String> getIp(HttpServletRequest request) {
String clientIp = IpUtil.getClientIp(request);
log.info("用户ip是::{}", clientIp);
return ResultUtils.success(clientIp);
}
3、代码原理的幽默解密
现在,就像是掀开魔术师的帽子,揭秘里面的兔子一样,我们来看看代码背后的秘密。这不仅仅是代码,这是一场编程魔法表演!
- X光视力启动 :我们的英雄首先使用
X-Forwarded-For
来寻找IP,就像是使用超级显微镜观察细菌。 - 多重身份大揭秘:如果IP地址试图使用伪装技巧(比如藏在一串地址中),别担心,我们的侦探能识破它们的伎俩,只抓取第一个!
- 深入敌后:如果上面的方法不奏效,我们的英雄就会变换战术,尝试其他的秘密通
道,比如Proxy-Client-IP
或WL-Proxy-Client-IP
。这就像是在玩一场"抓迷藏"的游戏,IP地址藏得再好,也逃不过我们的侦探。
- 最终绝技:本地侦测 :如果所有的技巧都失败了,我们的超级侦探
IpUtil
就会使用它的终极绝技------getRemoteAddr()
。这就像是超级英雄的最后一招,直接透视到请求的核心,揭露真相! - 意外转折:本地回环探秘 :有时候,最难找的IP地址就藏在"家里"(也就是本地地址)。这时,我们的英雄会展示他的侦探才能,调用
InetAddress.getLocalHost().getHostAddress()
,就像是在自己家里找遗失的钥匙一样!
java
1、public static String getClientIp(HttpServletRequest request) {
//这是一个静态方法的声明,意味着它可以在不创建类的实例的情况下被调用。方法返回一个字符串,表示客户端的IP地址。方法接收一个HttpServletRequest对象作为参数,这个对象代表了当前的HTTP请求。
2、String ip = request.getHeader("X-Forwarded-For");
//这一行尝试从HTTP请求头中获取名为X-Forwarded-For的值。X-Forwarded-For是一个标准的HTTP请求头,通常由代理服务器(如负载均衡器、CDN等)设置,用于转发原始请求者的IP地址。当一个请求经过代理时,代理服务器会在X-Forwarded-For头中追加该请求的原始IP地址。(代理ip也可以拿到)
3、 if (ip != null) {
// 处理多个IP的情况,获取第一个非未知的IP
ip = ip.split(",")[0].trim();
} else {
ip = request.getHeader("Proxy-Client-IP");
}
//这段代码首先检查X-Forwarded-For头是否不为空。如果不为空,可能包含了由逗号分隔的多个IP地址(当请求经过多个代理时会发生这种情况)。此时,代码取第一个IP地址作为客户端的IP。如果X-Forwarded-For为空,代码接着尝试获取Proxy-Client-IP头,这也是一种常见的代理服务器使用的头部。
4、 if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
ip = request.getHeader("WL-Proxy-Client-IP");
}
//这一行检查如果ip仍然是空的、长度为0,或者是字符串"unknown",则尝试从请求头WL-Proxy-Client-IP中获取IP地址。WL-Proxy-Client-IP是WebLogic服务器使用的头部,用于同样的目的。
5、 if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
ip = request.getHeader("X-Real-IP");
}
//类似地,如果ip还是未知,代码会尝试从X-Real-IP头获取IP地址。X-Real-IP通常被一些代理服务器和负载均衡器用来转发原始的IP地址。
6、 if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
ip = request.getRemoteAddr();
if ("127.0.0.1".equals(ip) || "0:0:0:0:0:0:0:1".equals(ip)) {
// 获取本机真实IP
try {
ip = InetAddress.getLocalHost().getHostAddress();
} catch (UnknownHostException e) {
// IP地址获取失败
ip = "unknown";
}
}
}
//如果前面的所有步骤都未能获取到IP地址,最后使用request.getRemoteAddr()方法获取发起请求的IP地址。这通常是直接与服务器连接的客户端的IP地址。如果这个地址是本地回环地址(即127.0.0.1或0:0:0:0:0:0:0:1),则尝试获取本机的真实IP地址。这里使用了InetAddress.getLocalHost().getHostAddress()方法。如果无法获取本机地址(如因为未知的主机异常),则将IP设为"unknown"。
7、HttpServletRequest是Java Servlet API中的一个接口,代表客户端发起的一个HTTP请求。当一个客户端(如Web浏览器)向服务器发送请求时,Servlet容器(如Tomcat)会创建一个HttpServletRequest对象,并将其传递给适当的Servlet处理。这个对象包含了所有关于该HTTP请求的信息,比如请求头、参数、URL、HTTP方法等。在Spring Boot应用中,你可以在控制器(Controller)的方法中使用HttpServletRequest来获取这些信息。
4、总结:编程的魔法世界
这就是我们的编程魔法表演!一个充满惊喜、挑战和幽默的旅程。记住,每当你在键盘上敲下代码,你就是在施展魔法,每一行代码都是一种咒语,每一个函数都是一次魔法冒险。
在这个故事中,我们不仅学会了如何使用Java找到客户端IP,还体验了编程的乐趣和魔力。所以下次当你遇到编程难题时,别忘了,你有超级英雄IpUtil
和他的忠实助手controller
,以及一点编程魔法在你身边!君子性非异也,擅假于物也。