Nginx暴露出請(qǐng)求的真實(shí)IP的問(wèn)題
前言
在工作中,經(jīng)常會(huì)用用戶(hù)實(shí)際請(qǐng)求的 IP 地址,當(dāng)需要記錄到日志信息時(shí)或者在請(qǐng)求其他的第三方接口時(shí)需要用到實(shí)際的用戶(hù) IP 地址傳入,在本節(jié)中會(huì)提供服務(wù)端在實(shí)際獲取 IP 地址的源碼以及通過(guò) Nginx 代理后 IP 地址隱藏的問(wèn)題
用途/場(chǎng)景
獲取經(jīng)緯度
無(wú)論是小程序還是 App 端,當(dāng)用戶(hù)未開(kāi)啟地理位置授權(quán)時(shí),在前端頁(yè)面是無(wú)法拿到當(dāng)前用戶(hù)所在的經(jīng)緯度信息的,這時(shí)候還有另外一種途徑來(lái)獲取經(jīng)緯度,那就是通過(guò) IP 地址來(lái)解析用戶(hù)真實(shí)請(qǐng)求時(shí)所在的經(jīng)緯度
在一般情況下,都是由前端來(lái)拿到這塊請(qǐng)求的 IP,可能由于某些 API 或版本的限制,導(dǎo)致前端在所獲取的 IP 地址不準(zhǔn)確,此時(shí),不得不讓后端的大佬 CASE 出手了
支付接口
微信 > 小程序支付文檔中,終端IP:spbill_create_ip 參數(shù)是必填項(xiàng),雖然在微信那一側(cè)不會(huì)去校驗(yàn)這塊的 IP 地址是否準(zhǔn)確,但真實(shí)的 IP 地址有利用我們?nèi)ヅ挪榫€(xiàn)上問(wèn)題,比如 IP 地址都是 127.0.0.1 這樣的,你永遠(yuǎn)都分辨不出到底請(qǐng)求是從那一塊服務(wù)進(jìn)來(lái)的
白名單配置
當(dāng)請(qǐng)求第三方接口 API 時(shí),若我們所請(qǐng)求的 IP 地址未配置進(jìn)白名單時(shí),我們是無(wú)法從第三方獲取到我們想要得到的信息的,這時(shí)候有了前置或后置日志打印我們請(qǐng)求時(shí)的 IP,能夠更快的幫助我們解決問(wèn)題
比較友善的第三方 API,在我們請(qǐng)求接口出現(xiàn)白名單的問(wèn)題,會(huì)將我們的 IP 進(jìn)行返回提示 “該 IP:Xxx,未配置白名單,請(qǐng)聯(lián)系管理員!”,這時(shí)直接拿到返回的錯(cuò)誤信息內(nèi)容進(jìn)行配置即可,無(wú)須任何的日志輸入
但是有的第三方 API 就比較雞肋,只是返回一段 "請(qǐng)求 IP 未配置白名單,請(qǐng)聯(lián)系管理員!”,這時(shí)候如果不+日志打印,那中間去找部署服務(wù)的 IP 花費(fèi)的時(shí)間就比這日志打印的時(shí)間多了個(gè)去
實(shí)現(xiàn)源碼
請(qǐng)求工具類(lèi)
/** * @author vnjohn * @since 2023/10/30 */ public class IPv4Util { private static final String HEADER_FORWARDED_FOR = "x-forwarded-for"; private static final String HEADER_PROXY_CLIENT_IP = "Proxy-Client-IP"; private static final String HEADER_WL_PROXY_CLIENT_IP = "WL-Proxy-Client-IP"; private static final String HEADER_HTTP_CLIENT_IP = "http_client_ip"; private static final String HEADER_HTTP_X_FORWARDED_FOR = "HTTP_X_FORWARDED_FOR"; private static final String UNKNOWN = "unknown"; private static final String CHAR_COLON = ":"; private static final String CHAR_COMMA = ","; public static String getClientIp(HttpServletRequest request) { String ip = request.getHeader(HEADER_FORWARDED_FOR); boolean ipIsEmpty = ip == null || ip.length() == 0; if (ipIsEmpty || UNKNOWN.equalsIgnoreCase(ip)) { ip = request.getHeader(HEADER_PROXY_CLIENT_IP); } if (ipIsEmpty || UNKNOWN.equalsIgnoreCase(ip)) { ip = request.getHeader(HEADER_WL_PROXY_CLIENT_IP); } if (ipIsEmpty || UNKNOWN.equalsIgnoreCase(ip)) { ip = request.getRemoteAddr(); } if (ipIsEmpty || UNKNOWN.equalsIgnoreCase(ip)) { ip = request.getHeader(HEADER_HTTP_CLIENT_IP); } if (ipIsEmpty || UNKNOWN.equalsIgnoreCase(ip)) { ip = request.getHeader(HEADER_HTTP_X_FORWARDED_FOR); } // 如果是多級(jí)代理,那么取第一個(gè)ip為客戶(hù)ip if (ip != null && ip.contains(CHAR_COMMA)) { ip = ip.substring(ip.lastIndexOf(CHAR_COMMA) + 1, ip.length()).trim(); } //判斷IP是否存在帶有端口號(hào)的情況、應(yīng)該要去掉端口號(hào) if (ip != null && ip.contains(CHAR_COLON)) { ip = ip.substring(0, ip.indexOf(CHAR_COLON)); } return ip; } /** * 獲取請(qǐng)求的ip */ public static String getRequestIp() { RequestAttributes requestAttributes = RequestContextHolder.getRequestAttributes(); // 從獲取 RequestAttributes 中獲取 HttpServletRequest 信息 HttpServletRequest request = (HttpServletRequest) requestAttributes.resolveReference(RequestAttributes.REFERENCE_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 ip; } public static void main(String[] args) { System.out.println(getRequestIp()); } }
在其他地方,需要獲取 IP 時(shí),只需要按如下傳入?yún)?shù):
HttpServletRequest request
如下調(diào)用即可:
IPv4Util.getClientIp(request);
Nginx 代理配置
在 server 標(biāo)簽?zāi)K中指定的請(qǐng)求前綴配置一個(gè) location 或直接在 server 標(biāo)簽內(nèi)進(jìn)行配置,如下:
location /app { proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_pass http://localhost:8084; }
只有當(dāng)設(shè)置了 proxy_set_header X-Real-IP 代理參數(shù)以后,獲取服務(wù)請(qǐng)求的 IP 才是準(zhǔn)確的
小結(jié)
注意:只有在 Nginx 代理配置以下內(nèi)容以后,通過(guò)請(qǐng)求工具類(lèi)才能獲取到真實(shí)的 IP 地址!??!
總結(jié)
該篇博文主要介紹的是如何在服務(wù)端中獲取用戶(hù)請(qǐng)求的真實(shí) IP 地址,通過(guò)幾種用途/場(chǎng)景介紹其所在的必要性:獲取經(jīng)緯度、支付接口、白名單配置,當(dāng)然,為了讓你能夠快速的運(yùn)用起來(lái),提供了請(qǐng)求工具類(lèi)的源碼以及告知你如何在 Nginx 進(jìn)行代理配置,希望這篇短文能夠幫助到您,解決您實(shí)際工作中的一些問(wèn)題
到此這篇關(guān)于Nginx暴露出請(qǐng)求的真實(shí)IP的問(wèn)題解決的文章就介紹到這了,更多相關(guān)Nginx暴露請(qǐng)求的真實(shí)IP內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
nginx中配置使用proxy?protocol協(xié)議的全過(guò)程
proxy protocol是一個(gè)Internet協(xié)議,通過(guò)為tcp添加一個(gè)很小的頭信息,來(lái)方便的傳遞客戶(hù)端信息,在網(wǎng)絡(luò)情況復(fù)雜又需要獲取用戶(hù)真實(shí)IP時(shí)非常有用,這篇文章主要給大家介紹了關(guān)于nginx中配置使用proxy?protocol協(xié)議的相關(guān)資料,需要的朋友可以參考下2022-04-04國(guó)外著名論壇程序IPB(Invision Power Board)在nginx下的配置示例
這篇文章主要介紹了國(guó)外著名論壇程序IPB(Invision Power Board)在nginx下的配置示例,使用fastcgi配置模式,需要的朋友可以參考下2014-07-07Nginx中禁止使用IP訪(fǎng)問(wèn)網(wǎng)站的配置實(shí)例
這篇文章主要介紹了Nginx中禁止使用IP訪(fǎng)問(wèn)網(wǎng)站的配置實(shí)例,一般在備案時(shí)可能需要這種設(shè)置,需要的朋友可以參考下2014-07-07nginx提示:500 Internal Server Error錯(cuò)誤解決辦法
這篇文章主要介紹了 nginx提示:500 Internal Server Error錯(cuò)誤解決辦法的相關(guān)資料,這里提供了解決該問(wèn)題的詳細(xì)步驟,希望能幫助到大家,需要的朋友可以參考下2017-08-08Nginx捕獲并自定義proxy_pass返回的錯(cuò)誤問(wèn)題
這篇文章主要介紹了Nginx捕獲并自定義proxy_pass返回的錯(cuò)誤問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2024-06-06nginx反向代理導(dǎo)致session失效的問(wèn)題解決
這篇文章主要介紹了nginx反向代理導(dǎo)致session失效的問(wèn)題解決,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2020-06-06Nginx代理Vue項(xiàng)目出現(xiàn)Invalid Host header問(wèn)題及解決
在使用Nginx的upstream對(duì)Vue項(xiàng)目進(jìn)行負(fù)載均衡時(shí),如果代理地址無(wú)法訪(fǎng)問(wèn)目標(biāo)地址且頁(yè)面報(bào)錯(cuò)InvalidHostheader(無(wú)效主機(jī)頭),可能是由于Vue項(xiàng)目的主機(jī)檢查配置導(dǎo)致的,解決方法是在Vue項(xiàng)目的webpack.dev.js文件中的devServer下添加disableHostCheck:true,跳過(guò)主機(jī)檢查2024-12-12Nginx?請(qǐng)求超時(shí)的實(shí)現(xiàn)
Nginx請(qǐng)求超時(shí)是服務(wù)器無(wú)法在規(guī)定時(shí)間內(nèi)完成對(duì)客戶(hù)端請(qǐng)求的響應(yīng),本文就來(lái)介紹一下Nginx?請(qǐng)求超時(shí)的實(shí)現(xiàn),具有一定的參考價(jià)值,感興趣的可以了解一下2025-02-02