Java 获取请求者的 IP 每次不一样

在开发 Web 应用程序时,经常需要获取请求者的 IP 地址。然而,由于网络架构的多样性以及代理服务器的存在,获取请求者的真实 IP 地址变得有些复杂。在本文中,我们将介绍如何使用 Java 获取请求者的 IP 地址,并解决每次获取到的 IP 不一样的问题。

获取请求者的 IP 地址

一般情况下,我们可以使用 HttpServletRequest 对象的 getRemoteAddr() 方法来获取请求者的 IP 地址。示例如下:

String ipAddress = request.getRemoteAddr();

然而,这种方式并不总是能够获取到真实的 IP 地址,尤其是在存在代理服务器的情况下。代理服务器充当了客户端和服务器之间的中间人,可能会修改请求头并传递给服务器。因此,我们需要考虑到代理服务器的影响,以获取真实的 IP 地址。

解决代理服务器的影响

代理服务器通常会在请求中添加 X-Forwarded-ForX-Real-IP 头部信息,用于指示原始的客户端 IP 地址。我们可以通过检查这些头部信息来获取真实的 IP 地址。

以下是一个使用 X-Forwarded-For 头部信息的示例代码:

String ipAddress = request.getHeader("X-Forwarded-For");
if (ipAddress == null || ipAddress.isEmpty() || "unknown".equalsIgnoreCase(ipAddress)) {
    ipAddress = request.getHeader("Proxy-Client-IP");
}
if (ipAddress == null || ipAddress.isEmpty() || "unknown".equalsIgnoreCase(ipAddress)) {
    ipAddress = request.getHeader("WL-Proxy-Client-IP");
}
if (ipAddress == null || ipAddress.isEmpty() || "unknown".equalsIgnoreCase(ipAddress)) {
    ipAddress = request.getHeader("HTTP_CLIENT_IP");
}
if (ipAddress == null || ipAddress.isEmpty() || "unknown".equalsIgnoreCase(ipAddress)) {
    ipAddress = request.getHeader("HTTP_X_FORWARDED_FOR");
}
if (ipAddress == null || ipAddress.isEmpty() || "unknown".equalsIgnoreCase(ipAddress)) {
    ipAddress = request.getRemoteAddr();
}

上述代码首先尝试从 X-Forwarded-For 头部信息中获取 IP 地址,如果为空或者为 "unknown",则依次尝试获取其他头部信息,最后才使用 getRemoteAddr() 方法获取。

获取请求者的真实 IP 地址

尽管通过检查头部信息可以获取到客户端的真实 IP 地址,但是在某些情况下,代理服务器可能会隐藏真实 IP 地址,或者伪造 IP 地址。为了获取更加准确的 IP 地址,我们可以使用 ServletRequestgetRemoteHost() 方法来获取主机名,并使用 InetAddress 类的 getByName() 方法将主机名解析为 IP 地址。

以下是一个获取真实 IP 地址的示例代码:

String ipAddress = request.getHeader("X-Forwarded-For");
if (ipAddress == null || ipAddress.isEmpty() || "unknown".equalsIgnoreCase(ipAddress)) {
    ipAddress = request.getHeader("Proxy-Client-IP");
}
if (ipAddress == null || ipAddress.isEmpty() || "unknown".equalsIgnoreCase(ipAddress)) {
    ipAddress = request.getHeader("WL-Proxy-Client-IP");
}
if (ipAddress == null || ipAddress.isEmpty() || "unknown".equalsIgnoreCase(ipAddress)) {
    ipAddress = request.getHeader("HTTP_CLIENT_IP");
}
if (ipAddress == null || ipAddress.isEmpty() || "unknown".equalsIgnoreCase(ipAddress)) {
    ipAddress = request.getHeader("HTTP_X_FORWARDED_FOR");
}
if (ipAddress == null || ipAddress.isEmpty() || "unknown".equalsIgnoreCase(ipAddress)) {
    ipAddress = request.getRemoteAddr();
} else {
    try {
        InetAddress inetAddress = InetAddress.getByName(ipAddress);
        ipAddress = inetAddress.getHostAddress();
    } catch (UnknownHostException e) {
        // 处理异常
    }
}

上述代码在获取到 IP 地址后,通过 InetAddress 类将主机名解析为 IP 地址,以获取更加准确的 IP 地址。

总结

通过以上的代码示例,我们可以使用 Java 获取请求者的 IP 地址,并解决了代理服务器的影响。需要注意的是,由于网络架构的多样性,无法保证每次获取到的 IP 地址都是准确的。因此,在实际开发中,我们应该根据具体情