首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> Java 程式設計 >> Java 相關知識

Java 獲取客戶端真實 IP 完整指南:代理穿透與多級轉發處理

     編輯:Java 相關知識

直接獲取 IP 的局限性

在 JSP/Servlet 中使用 request.getRemoteAddr() 可取得客戶端 IP,但經過 Apache、Squid、Nginx 等反向代理後,該方法只會返回代理伺服器 IP(如 127.0.0.1 或內網位址),而非真實客戶端 IP。

HTTP 標頭傳遞機制

代理轉發請求時,會在 HTTP 標頭加入 X-Forwarded-For(簡稱 XFF)欄位,記錄原始客戶端 IP 與轉發鏈路。標準格式為:

X-Forwarded-For: client, proxy1, proxy2

最左側為最原始客戶端 IP,依序為經過的代理節點。

基本獲取策略

方案一:單純檢查 XFF

public String getRemoteIP(HttpServletRequest request) {
  String xff = request.getHeader("x-forwarded-for");
  return (xff == null) ? request.getRemoteAddr() : xff;
}

方案二:多標頭相容回退

public String getIpAddr(HttpServletRequest request) {
  String ip = request.getHeader("x-forwarded-for");
  if (ip == null || ip.isEmpty() || "unknown".equalsIgnoreCase(ip)) {
    ip = request.getHeader("Proxy-Client-IP");
  }
  if (ip == null || ip.isEmpty() || "unknown".equalsIgnoreCase(ip)) {
    ip = request.getHeader("WL-Proxy-Client-IP");
  }
  if (ip == null || ip.isEmpty() || "unknown".equalsIgnoreCase(ip)) {
    ip = request.getRemoteAddr();
  }
  return ip;
}

多級代理下的真實 IP 識別

當經過多級反向代理,X-Forwarded-For 會包含一串 IP:

X-Forwarded-For: 192.168.1.110, 192.168.1.120, 192.168.1.130, 192.168.1.100

真實客戶端 IP 為第一個非 unknown 的有效 IP,即 192.168.1.110。

健壯解析實作

public String getRealIp(HttpServletRequest request) {
  String xff = request.getHeader("X-Forwarded-For");
  if (xff != null && !xff.isEmpty() && !"unknown".equalsIgnoreCase(xff)) {
    // 取第一個有效 IP
    String[] ips = xff.split(",");
    for (String ip : ips) {
      String trimmed = ip.trim();
      if (!trimmed.isEmpty() && !"unknown".equalsIgnoreCase(trimmed)) {
        return trimmed;
      }
    }
  }
  // 回退其他標頭
  String[] headers = {"Proxy-Client-IP", "WL-Proxy-Client-IP", "HTTP_CLIENT_IP", "HTTP_X_FORWARDED_FOR"};
  for (String header : headers) {
    String ip = request.getHeader(header);
    if (ip != null && !ip.isEmpty() && !"unknown".equalsIgnoreCase(ip)) {
      return ip;
    }
  }
  return request.getRemoteAddr();
}

安全性考量與最佳實踐

  • 信任邊界:僅信任已知代理層傳遞的標頭,防止客戶端偽造 XFF
  • IP 格式驗證:解析後應驗證 IPv4/IPv6 格式合法性
  • 內網 IP 過濾:若第一個 IP 為私有位址(10.x、172.16-31.x、192.168.x),應往後尋找公網 IP
  • 框架整合:Spring Boot 可配置 server.forward-headers-strategy=framework 或使用 Filter 統一處理

總結

獲取真實 IP 核心在於正確解析 X-Forwarded-For 鏈路,取首個有效非未知 IP,並建立多層回退機制。生產環境務必結合信任代理清單與 IP 驗證,防範標頭偽造攻擊。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved