杰瑞科技汇

Java如何准确获取客户端真实IP地址?

在Java中获取客户端IP地址

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

Java如何准确获取客户端真实IP地址?-图1
(图片来源网络,侵删)

基本方法(直接获取)

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;
    }
}

注意事项

  1. X-Forwarded-For头:这个头可能包含多个IP地址,第一个IP是客户端的真实IP,后面的是经过的代理服务器IP。

    Java如何准确获取客户端真实IP地址?-图2
    (图片来源网络,侵删)
  2. 安全性:这些HTTP头可以被伪造,因此不要完全信任它们,在生产环境中,应该考虑使用更可靠的方法或结合其他验证机制。

  3. IPv6地址:上述代码可能需要调整以正确处理IPv6地址。

  4. 本地访问:当应用在本地运行时,getRemoteAddr()可能会返回0.0.10:0:0:0:0:0:0:1(IPv6的localhost)。

  5. 反向代理配置:确保反向代理(如Nginx、Apache)正确设置了这些头信息。

    Java如何准确获取客户端真实IP地址?-图3
    (图片来源网络,侵删)

使用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);
}

选择哪种方法取决于你的应用架构和部署环境,对于简单的应用,第一种方法可能就足够了;对于企业级应用,建议使用更全面的第二种方法。

分享:
扫描分享到社交APP
上一篇
下一篇