欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

SpringBoot通過Nginx代理獲取真實(shí)IP

 更新時(shí)間:2024年01月16日 09:11:47   作者:北風(fēng)濁酒  
springboot作為后臺(tái)代碼,獲取到的登錄IP是前臺(tái)的代理服務(wù)器地址,并不是用戶的真實(shí)IP地址,本文主要介紹了SpringBoot通過Nginx代理獲取真實(shí)IP,具有一定的參考價(jià)值,感興趣的可以了解一下

springboot作為后臺(tái)代碼,獲取到的登錄IP是前臺(tái)的代理服務(wù)器地址,并不是用戶的真實(shí)IP地址,讓我們?cè)谧鼋y(tǒng)計(jì)的時(shí)候無從下手。下面是一個(gè)后臺(tái)獲取IP地址的類,本質(zhì)上沒有什么問題,問題在于,Nginx給你的就是一個(gè)代理之后的地址,所以你當(dāng)然獲取不到真實(shí)的地址了。

package com.**.common.core.utils.ip;

import java.net.InetAddress;
import java.net.UnknownHostException;
import javax.servlet.http.HttpServletRequest;
import com.**.common.core.utils.StringUtils;
import org.springframework.http.HttpHeaders;
import org.springframework.http.server.reactive.ServerHttpRequest;

/**
 * 獲取IP方法
 * 
 * @author Hxhh
 */
public class IpUtils
{
    /**
     * 獲取客戶端IP
     * 
     * @param request 請(qǐng)求對(duì)象
     * @return IP地址
     */
    public static String getIpAddr(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();
        }

        return "0:0:0:0:0:0:0:1".equals(ip) ? "127.0.0.1" : getMultistageReverseProxyIp(ip);
    }

    public static String getIpAddr(ServerHttpRequest request) {
        HttpHeaders headers = request.getHeaders();
        String ip = headers.getFirst("x-forwarded-for");
        if (ip != null && ip.length() != 0 && !"unknown".equalsIgnoreCase(ip)) {
            // 多次反向代理后會(huì)有多個(gè)ip值,第一個(gè)ip才是真實(shí)ip
            if (ip.indexOf(",") != -1) {
                ip = ip.split(",")[0];
            }
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = headers.getFirst("Proxy-Client-IP");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = headers.getFirst("WL-Proxy-Client-IP");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = headers.getFirst("HTTP_CLIENT_IP");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = headers.getFirst("HTTP_X_FORWARDED_FOR");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = headers.getFirst("X-Real-IP");
        }
        if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
            ip = request.getRemoteAddress().getAddress().getHostAddress();
        }
        return ip;
    }


    /**
     * 檢查是否為內(nèi)部IP地址
     * 
     * @param ip IP地址
     * @return 結(jié)果
     */
    public static boolean internalIp(String ip)
    {
        byte[] addr = textToNumericFormatV4(ip);
        return internalIp(addr) || "127.0.0.1".equals(ip);
    }

    /**
     * 檢查是否為內(nèi)部IP地址
     * 
     * @param addr byte地址
     * @return 結(jié)果
     */
    private static boolean internalIp(byte[] addr)
    {
        if (StringUtils.isNull(addr) || addr.length < 2)
        {
            return true;
        }
        final byte b0 = addr[0];
        final byte b1 = addr[1];
        // 10.x.x.x/8
        final byte SECTION_1 = 0x0A;
        // 172.16.x.x/12
        final byte SECTION_2 = (byte) 0xAC;
        final byte SECTION_3 = (byte) 0x10;
        final byte SECTION_4 = (byte) 0x1F;
        // 192.168.x.x/16
        final byte SECTION_5 = (byte) 0xC0;
        final byte SECTION_6 = (byte) 0xA8;
        switch (b0)
        {
            case SECTION_1:
                return true;
            case SECTION_2:
                if (b1 >= SECTION_3 && b1 <= SECTION_4)
                {
                    return true;
                }
            case SECTION_5:
                switch (b1)
                {
                    case SECTION_6:
                        return true;
                }
            default:
                return false;
        }
    }

    /**
     * 將IPv4地址轉(zhuǎn)換成字節(jié)
     * 
     * @param text IPv4地址
     * @return byte 字節(jié)
     */
    public static byte[] textToNumericFormatV4(String text)
    {
        if (text.length() == 0)
        {
            return null;
        }

        byte[] bytes = new byte[4];
        String[] elements = text.split("\\.", -1);
        try
        {
            long l;
            int i;
            switch (elements.length)
            {
                case 1:
                    l = Long.parseLong(elements[0]);
                    if ((l < 0L) || (l > 4294967295L))
                    {
                        return null;
                    }
                    bytes[0] = (byte) (int) (l >> 24 & 0xFF);
                    bytes[1] = (byte) (int) ((l & 0xFFFFFF) >> 16 & 0xFF);
                    bytes[2] = (byte) (int) ((l & 0xFFFF) >> 8 & 0xFF);
                    bytes[3] = (byte) (int) (l & 0xFF);
                    break;
                case 2:
                    l = Integer.parseInt(elements[0]);
                    if ((l < 0L) || (l > 255L))
                    {
                        return null;
                    }
                    bytes[0] = (byte) (int) (l & 0xFF);
                    l = Integer.parseInt(elements[1]);
                    if ((l < 0L) || (l > 16777215L))
                    {
                        return null;
                    }
                    bytes[1] = (byte) (int) (l >> 16 & 0xFF);
                    bytes[2] = (byte) (int) ((l & 0xFFFF) >> 8 & 0xFF);
                    bytes[3] = (byte) (int) (l & 0xFF);
                    break;
                case 3:
                    for (i = 0; i < 2; ++i)
                    {
                        l = Integer.parseInt(elements[i]);
                        if ((l < 0L) || (l > 255L))
                        {
                            return null;
                        }
                        bytes[i] = (byte) (int) (l & 0xFF);
                    }
                    l = Integer.parseInt(elements[2]);
                    if ((l < 0L) || (l > 65535L))
                    {
                        return null;
                    }
                    bytes[2] = (byte) (int) (l >> 8 & 0xFF);
                    bytes[3] = (byte) (int) (l & 0xFF);
                    break;
                case 4:
                    for (i = 0; i < 4; ++i)
                    {
                        l = Integer.parseInt(elements[i]);
                        if ((l < 0L) || (l > 255L))
                        {
                            return null;
                        }
                        bytes[i] = (byte) (int) (l & 0xFF);
                    }
                    break;
                default:
                    return null;
            }
        }
        catch (NumberFormatException e)
        {
            return null;
        }
        return bytes;
    }

    /**
     * 獲取IP地址
     * 
     * @return 本地IP地址
     */
    public static String getHostIp()
    {
        try
        {
            return InetAddress.getLocalHost().getHostAddress();
        }
        catch (UnknownHostException e)
        {
        }
        return "127.0.0.1";
    }

    /**
     * 獲取主機(jī)名
     * 
     * @return 本地主機(jī)名
     */
    public static String getHostName()
    {
        try
        {
            return InetAddress.getLocalHost().getHostName();
        }
        catch (UnknownHostException e)
        {
        }
        return "未知";
    }

    /**
     * 從多級(jí)反向代理中獲得第一個(gè)非unknown IP地址
     *
     * @param ip 獲得的IP地址
     * @return 第一個(gè)非unknown IP地址
     */
    public static String getMultistageReverseProxyIp(String ip)
    {
        // 多級(jí)反向代理檢測(cè)
        if (ip != null && ip.indexOf(",") > 0)
        {
            final String[] ips = ip.trim().split(",");
            for (String subIp : ips)
            {
                if (false == isUnknown(subIp))
                {
                    ip = subIp;
                    break;
                }
            }
        }
        return ip;
    }

    /**
     * 檢測(cè)給定字符串是否為未知,多用于檢測(cè)HTTP請(qǐng)求相關(guān)
     *
     * @param checkString 被檢測(cè)的字符串
     * @return 是否未知
     */
    public static boolean isUnknown(String checkString)
    {
        return StringUtils.isBlank(checkString) || "unknown".equalsIgnoreCase(checkString);
    }
}

那么如何識(shí)別客戶端的真實(shí)IP呢,需要通過兩種方式去判斷:

1、沒有代理
如果只是普通的web項(xiàng)目的話,通過 request.getRemoteAddr(); (HttpServletRequest 類型) 即可獲取到客戶端的真實(shí)IP

2、Nginx代理
在有代理的情況下,由于任何請(qǐng)求首先經(jīng)過Nginx,故通過request.getRemoteAddr()獲取的其實(shí)是Nginx的IP,并非真實(shí)的客戶端IP;此時(shí)通過x-forwarded-for獲取的IP為:"客戶端,代理1,代理2,..."或者"偽造IP,客戶端,代理1,代理2,...",故不能獲取到準(zhǔn)確的客戶端IP,此時(shí)需要配置Nginx TCP客戶端連接的真實(shí)IP,通過代理配置獲取真實(shí)IP,可以通過$remote_addr獲取客戶端IP,Nginx配置如下:

location / {
   //追加如下代碼
   proxy_set_header X-Real-IP $remote_addr;
   proxy_set_header Host $host;
   proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
 
}

然后服務(wù)端通過: request.getHeader("X-Real-IP");    即可獲取到客戶端的真實(shí)IP

到此這篇關(guān)于SpringBoot通過Nginx代理獲取真實(shí)IP的文章就介紹到這了,更多相關(guān)SpringBoot Nginx獲取真實(shí)IP內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Spring中統(tǒng)一異常處理示例詳解

    Spring中統(tǒng)一異常處理示例詳解

    這篇文章主要給大家介紹了關(guān)于Spring中統(tǒng)一異常處理的相關(guān)資料,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家學(xué)習(xí)或者使用spring具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2018-09-09
  • JVM內(nèi)存模型/內(nèi)存空間:運(yùn)行時(shí)數(shù)據(jù)區(qū)

    JVM內(nèi)存模型/內(nèi)存空間:運(yùn)行時(shí)數(shù)據(jù)區(qū)

    這篇文章主要介紹了JVM內(nèi)存模型/內(nèi)存空間的相關(guān)資料,幫助大家更好的理解和學(xué)習(xí)Java虛擬機(jī),感興趣的朋友可以了解詳細(xì),希望能夠給你帶來幫助
    2021-08-08
  • Spring入門到精通之注解開發(fā)詳解

    Spring入門到精通之注解開發(fā)詳解

    Spring是輕代碼而重配置的框架,配置比較繁重,影響開發(fā)效率,所以注解開發(fā)是一種趨勢(shì)。本文將通過示例為大家詳細(xì)講講Spring如何實(shí)現(xiàn)注解開發(fā),感興趣的可以學(xué)習(xí)一下
    2022-07-07
  • 詳解mybatis流式查詢與分頁插件

    詳解mybatis流式查詢與分頁插件

    這篇文章主要介紹了mybatis流式查詢與分頁插件,本文通過實(shí)例代碼給大家講解的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2022-11-11
  • 淺談Java線程池是如何運(yùn)行的

    淺談Java線程池是如何運(yùn)行的

    這篇文章主要介紹了淺談Java線程池是如何運(yùn)行的,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-11-11
  • springboot集成flyway自動(dòng)創(chuàng)表的詳細(xì)配置

    springboot集成flyway自動(dòng)創(chuàng)表的詳細(xì)配置

    Flayway是一款數(shù)據(jù)庫版本控制管理工具,支持?jǐn)?shù)據(jù)庫版本自動(dòng)升級(jí),Migrations可以寫成sql腳本,也可以寫在java代碼里;本文通過實(shí)例代碼給大家介紹springboot集成flyway自動(dòng)創(chuàng)表的詳細(xì)過程,感興趣的朋友一起看看吧
    2021-06-06
  • 一文詳解如何使用Java分割PDF文件

    一文詳解如何使用Java分割PDF文件

    PDF是一種用于顯示和打印文檔的文件格式,它非常廣泛地應(yīng)用于電子書籍、報(bào)告、合同等文件的傳遞和共享,這篇文章主要給大家介紹了關(guān)于如何使用Java分割PDF文件的相關(guān)資料,需要的朋友可以參考下
    2024-01-01
  • 最新評(píng)論