通過 HttpServletRequest 獲取客戶端 IP 地址


在 Java Web 應用中,想要在接口中獲取到發送請求的客戶端 IP 地址,需要依賴請求對象 —— HttpServletRequest。

那么,首先就是要先獲取到請求的對象。

在 Spring Boot 中,只需在接口方法上加上 HttpServletRequest 或 HttpServletResponse 參數,Spring Boot 就會自動綁定這兩個對象,然后可以直接使用。如果你的方法有其他參數,只需把這兩個加到后面即可。例如:

@GetMapping("/getSomething")
public String getSomething(..., HttpServletRequest request, HttpServletResponse response) {
    //...
}

這是最常用的一種方法,當然除了這種方式,在 Spring Boot 中還可以使用注解 @Autowired 注入或通過 RequestContextHolder 來獲取請求對象,這里就不展開敘述了。

在得到請求對象 HttpServletRequest 對象后,一般的,我們可以使用 request.getRemoteAddr() 來獲取到客戶端對應的 IP 地址。

但是,如果使用了 Nginx 等反向代理軟件,則不能只簡單地通過上述代碼來獲取 IP;並且,如果使用了多級反向代理的話,那么在獲取 X-Forwarded-For 的值時,得到的應是一串 IP 地址,此種情況下,X-Forwarded-For 中第一個非 unknown 的有效 IP 字符串,則為真實 IP 地址。

Talk is cheap, show me code.

下面是一個封裝的工具類,用於從 HttpServletRequest 對象中獲取相應的客戶端 IP 地址。

import javax.servlet.http.HttpServletRequest;
import java.net.InetAddress;
import java.net.UnknownHostException;

public class IpUtil {
    private static final String UNKNOWN = "unknown";
    private static final String LOCALHOST_IP = "127.0.0.1";
    // 客戶端與服務器同為一台機器,獲取的 ip 有時候是 ipv6 格式
    private static final String LOCALHOST_IPV6 = "0:0:0:0:0:0:0:1";
    private static final String SEPARATOR = ",";

    // 根據 HttpServletRequest 獲取 IP
    public static String getIpAddress(HttpServletRequest request) {
        if (request == null) {
            return "unknown";
        }
        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("X-Forwarded-For");
        }
        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("X-Real-IP");
        }
        if (ip == null || ip.length() == 0 || UNKNOWN.equalsIgnoreCase(ip)) {
            ip = request.getRemoteAddr();
            if (LOCALHOST_IP.equalsIgnoreCase(ip) || LOCALHOST_IPV6.equalsIgnoreCase(ip)) {
                // 根據網卡取本機配置的 IP
                InetAddress iNet = null;
                try {
                    iNet = InetAddress.getLocalHost();
                } catch (UnknownHostException e) {
                    e.printStackTrace();
                }
                if (iNet != null)
                    ip = iNet.getHostAddress();
            }
        }
        // 對於通過多個代理的情況,分割出第一個 IP
        if (ip != null && ip.length() > 15) {
            if (ip.indexOf(SEPARATOR) > 0) {
                ip = ip.substring(0, ip.indexOf(SEPARATOR));
            }
        }
        return LOCALHOST_IPV6.equals(ip) ? LOCALHOST_IP : ip;
    }
}


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM