凌峰创科服务平台

Servlet如何获取服务器真实IP地址?

获取客户端的 IP 地址

这是更常见的需求,比如用于记录访问日志、做地域限制、防刷等。

Servlet如何获取服务器真实IP地址?-图1
(图片来源网络,侵删)

客户端的 IP 地址可以通过 HttpServletRequest 对象获取,最直接的方法是 request.getRemoteAddr()

基本方法:request.getRemoteAddr()

这是获取客户端 IP 最直接、最常用的方法,它返回的是客户端发起请求的最后一个代理的 IP 地址。

import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
public class ClientIpServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException {
        String ipAddress = request.getRemoteAddr();
        response.setContentType("text/html;charset=UTF-8");
        response.getWriter().println("<h1>客户端 IP 地址</h1>");
        response.getWriter().println("<p>使用 getRemoteAddr() 获取的 IP 地址是: <strong>" + ipAddress + "</strong></p>");
    }
}

处理代理服务器(如 Nginx, Apache)的情况

当你的应用部署在反向代理(如 Nginx, Apache, HAProxy)后面时,request.getRemoteAddr() 获取到的将是代理服务器的 IP 地址,而不是客户端的真实 IP。

为了获取客户端的真实 IP,我们需要检查一个特殊的 HTTP 请求头:X-Forwarded-For

Servlet如何获取服务器真实IP地址?-图2
(图片来源网络,侵删)
  • X-Forwarded-For: 这个头字段用于记录 HTTP 请求经过的代理服务器列表,格式通常为 客户端IP, 代理1IP, 代理2IP, ...,最左边的 IP 是客户端的真实 IP。

获取客户端真实 IP 的逻辑是:

  1. 首先检查 request.getHeader("X-Forwarded-For")
  2. 如果该头存在且不为空,则取其第一个逗号左边的部分。
  3. 如果不存在,则回退到 request.getRemoteAddr()

推荐使用一个工具类来封装这个逻辑,因为它比较复杂,且需要考虑多个代理头的情况(如 Proxy-Client-IP, WL-Proxy-Client-IP 等)。

示例:IP 获取工具类

import javax.servlet.http.HttpServletRequest;
public class IpUtils {
    /**
     * 获取客户端的真实 IP 地址
     * @param request HttpServletRequest 对象
     * @return 客户端真实 IP 地址
     */
    public static String getClientIpAddress(HttpServletRequest request) {
        String ip = request.getHeader("X-Forwarded-For");
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            // X-Forwarded-For 为空,则尝试获取 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 = request.getHeader("WL-Proxy-Client-IP");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            // 如果以上都为空,则使用 getRemoteAddr() 获取
            ip = request.getRemoteAddr();
        }
        // 对于通过多个代理的情况,第一个IP为客户端真实IP,多个IP按照','分割
        if (ip != null && ip.contains(",")) {
            ip = ip.split(",")[0].trim();
        }
        return ip;
    }
}

在 Servlet 中使用工具类

Servlet如何获取服务器真实IP地址?-图3
(图片来源网络,侵删)
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
public class RealClientIpServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException {
        String realIp = IpUtils.getClientIpAddress(request);
        response.setContentType("text/html;charset=UTF-8");
        response.getWriter().println("<h1>客户端真实 IP 地址</h1>");
        response.getWriter().println("<p>使用工具类获取的真实 IP 地址是: <strong>" + realIp + "</strong></p>");
    }
}

获取服务器自身的 IP 地址

如果你想知道运行 Servlet 的那台服务器(物理机或虚拟机)的 IP 地址,你需要从服务器环境的上下文中获取。

获取服务器名称(主机名)

最简单的方法是获取服务器的主机名。

import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.net.InetAddress;
import java.net.UnknownHostException;
public class ServerInfoServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException {
        // 获取服务器名称(主机名)
        String serverName = request.getServerName();
        response.setContentType("text/html;charset=UTF-8");
        response.getWriter().println("<h1>服务器信息</h1>");
        response.getWriter().println("<p>服务器名称 (主机名): <strong>" + serverName + "</strong></p>");
    }
}

获取服务器 IP 地址

要获取服务器绑定的 IP 地址,你需要结合 HttpServletRequestjava.net.InetAddress

注意:一台服务器可能有多个网卡,绑定多个 IP 地址。request.getLocalAddr() 获取的是接收当前请求的那个网络接口的 IP 地址。

import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.net.InetAddress;
import java.net.UnknownHostException;
public class ServerIpServlet extends HttpServlet {
    @Override
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws IOException {
        // 方法一:获取接收请求的本地网络接口的 IP 地址
        String serverIp = request.getLocalAddr();
        // 方法二:通过主机名获取所有 IP 地址(可以获取到服务器的所有 IP)
        InetAddress localHost;
        try {
            localHost = InetAddress.getLocalHost();
            // 如果想获取所有 IP 地址,可以使用 NetworkInterface 类
            // 这里我们只获取主机名和默认 IP
            String hostName = localHost.getHostName();
            String allIps = localHost.getHostAddress(); // 这通常只返回一个 IP
            response.setContentType("text/html;charset=UTF-8");
            response.getWriter().println("<h1>服务器自身 IP 地址</h1>");
            response.getWriter().println("<p>通过 request.getLocalAddr() 获取的 IP: <strong>" + serverIp + "</strong></p>");
            response.getWriter().println("<p>通过 InetAddress.getLocalHost() 获取的主机名: <strong>" + hostName + "</strong></p>");
            response.getWriter().println("<p>通过 InetAddress.getLocalHost() 获取的 IP: <strong>" + allIps + "</strong></p>");
        } catch (UnknownHostException e) {
            response.getWriter().println("无法获取服务器主机信息: " + e.getMessage());
        }
    }
}
需求 方法 说明
获取客户端 IP request.getRemoteAddr() 直接获取,但可能受代理影响,得到的是代理的 IP。
获取客户端真实 IP request.getHeader("X-Forwarded-For") 必须处理代理服务器场景,建议使用封装好的工具类。
获取服务器主机名 request.getServerName() 获取服务器配置的主机名或域名。
获取服务器 IP request.getLocalAddr() 获取接收当前请求的本地网络接口的 IP 地址。
获取服务器所有 IP InetAddress.getLocalHost()NetworkInterface 获取服务器主机名和默认 IP,NetworkInterface 可用于获取所有 IP。

在实际开发中,请务必使用工具类来获取客户端真实 IP,因为你的应用几乎不可能直接暴露在公网,总会有反向代理存在。

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