在Java中获取客户端IP地址
在Java Web应用中获取客户端IP地址需要考虑多种情况,因为客户端可能通过代理服务器、负载均衡器等访问服务器,以下是几种常见的获取客户端IP的方法:

基本方法(直接获取)
String ipAddress = request.getRemoteAddr();
这种方法在客户端直接连接到服务器时有效,但如果使用了代理或负载均衡器,获取到的可能是代理服务器的IP。
考虑代理服务器的情况
当使用代理服务器时,真实的客户端IP可能会被保存在HTTP头中,以下是从不同HTTP头中获取IP的方法:
public String getClientIpAddress(HttpServletRequest request) {
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();
}
// 对于通过多个代理的情况,第一个IP为客户端真实IP,多个IP按照','分割
if (ipAddress != null && ipAddress.contains(",")) {
ipAddress = ipAddress.split(",")[0].trim();
}
return ipAddress;
}
Spring Boot中的实现
在Spring Boot应用中,可以创建一个工具类:
import javax.servlet.http.HttpServletRequest;
import org.springframework.stereotype.Component;
@Component
public class IpAddressUtil {
public String getClientIpAddress(HttpServletRequest request) {
String ip = request.getHeader("X-Forwarded-For");
if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
ip = request.getHeader("Proxy-Client-IP");
}
if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
ip = request.getHeader("WL-Proxy-Client-IP");
}
if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
ip = request.getHeader("HTTP_CLIENT_IP");
}
if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
ip = request.getHeader("HTTP_X_FORWARDED_FOR");
}
if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
ip = request.getRemoteAddr();
}
return "0:0:0:0:0:0:0:1".equals(ip) ? "127.0.0.1" : ip;
}
}
注意事项
-
X-Forwarded-For头:这个头可能包含多个IP地址,第一个IP是客户端的真实IP,后面的是经过的代理服务器IP。
(图片来源网络,侵删) -
安全性:这些HTTP头可以被伪造,因此不要完全信任它们,在生产环境中,应该考虑使用更可靠的方法或结合其他验证机制。
-
IPv6地址:上述代码可能需要调整以正确处理IPv6地址。
-
本地访问:当应用在本地运行时,
getRemoteAddr()可能会返回0.0.1或0:0:0:0:0:0:0:1(IPv6的localhost)。 -
反向代理配置:确保反向代理(如Nginx、Apache)正确设置了这些头信息。
(图片来源网络,侵删)
使用Spring的RequestContextUtils
如果你使用的是Spring框架,还可以考虑使用RequestContextUtils:
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import javax.servlet.http.HttpServletRequest;
public String getCurrentIpAddress() {
HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
return getClientIpAddress(request);
}
选择哪种方法取决于你的应用架构和部署环境,对于简单的应用,第一种方法可能就足够了;对于企业级应用,建议使用更全面的第二种方法。
