Nginx暴露出請求的真實IP的問題
前言
在工作中,經(jīng)常會用用戶實際請求的 IP 地址,當需要記錄到日志信息時或者在請求其他的第三方接口時需要用到實際的用戶 IP 地址傳入,在本節(jié)中會提供服務端在實際獲取 IP 地址的源碼以及通過 Nginx 代理后 IP 地址隱藏的問題
用途/場景
獲取經(jīng)緯度
無論是小程序還是 App 端,當用戶未開啟地理位置授權時,在前端頁面是無法拿到當前用戶所在的經(jīng)緯度信息的,這時候還有另外一種途徑來獲取經(jīng)緯度,那就是通過 IP 地址來解析用戶真實請求時所在的經(jīng)緯度
在一般情況下,都是由前端來拿到這塊請求的 IP,可能由于某些 API 或版本的限制,導致前端在所獲取的 IP 地址不準確,此時,不得不讓后端的大佬 CASE 出手了
支付接口
微信 > 小程序支付文檔中,終端IP:spbill_create_ip 參數(shù)是必填項,雖然在微信那一側(cè)不會去校驗這塊的 IP 地址是否準確,但真實的 IP 地址有利用我們?nèi)ヅ挪榫€上問題,比如 IP 地址都是 127.0.0.1 這樣的,你永遠都分辨不出到底請求是從那一塊服務進來的
白名單配置
當請求第三方接口 API 時,若我們所請求的 IP 地址未配置進白名單時,我們是無法從第三方獲取到我們想要得到的信息的,這時候有了前置或后置日志打印我們請求時的 IP,能夠更快的幫助我們解決問題
比較友善的第三方 API,在我們請求接口出現(xiàn)白名單的問題,會將我們的 IP 進行返回提示 “該 IP:Xxx,未配置白名單,請聯(lián)系管理員!”,這時直接拿到返回的錯誤信息內(nèi)容進行配置即可,無須任何的日志輸入
但是有的第三方 API 就比較雞肋,只是返回一段 "請求 IP 未配置白名單,請聯(lián)系管理員!”,這時候如果不+日志打印,那中間去找部署服務的 IP 花費的時間就比這日志打印的時間多了個去
實現(xiàn)源碼
請求工具類
/** * @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); } // 如果是多級代理,那么取第一個ip為客戶ip if (ip != null && ip.contains(CHAR_COMMA)) { ip = ip.substring(ip.lastIndexOf(CHAR_COMMA) + 1, ip.length()).trim(); } //判斷IP是否存在帶有端口號的情況、應該要去掉端口號 if (ip != null && ip.contains(CHAR_COLON)) { ip = ip.substring(0, ip.indexOf(CHAR_COLON)); } return ip; } /** * 獲取請求的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 時,只需要按如下傳入?yún)?shù):
HttpServletRequest request
如下調(diào)用即可:
IPv4Util.getClientIp(request);
Nginx 代理配置
在 server 標簽模塊中指定的請求前綴配置一個 location 或直接在 server 標簽內(nèi)進行配置,如下:
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; }
只有當設置了 proxy_set_header X-Real-IP 代理參數(shù)以后,獲取服務請求的 IP 才是準確的
小結(jié)
注意:只有在 Nginx 代理配置以下內(nèi)容以后,通過請求工具類才能獲取到真實的 IP 地址?。。?/p>
總結(jié)
該篇博文主要介紹的是如何在服務端中獲取用戶請求的真實 IP 地址,通過幾種用途/場景介紹其所在的必要性:獲取經(jīng)緯度、支付接口、白名單配置,當然,為了讓你能夠快速的運用起來,提供了請求工具類的源碼以及告知你如何在 Nginx 進行代理配置,希望這篇短文能夠幫助到您,解決您實際工作中的一些問題
到此這篇關于Nginx暴露出請求的真實IP的問題解決的文章就介紹到這了,更多相關Nginx暴露請求的真實IP內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關文章希望大家以后多多支持腳本之家!
相關文章
nginx中配置使用proxy?protocol協(xié)議的全過程
proxy protocol是一個Internet協(xié)議,通過為tcp添加一個很小的頭信息,來方便的傳遞客戶端信息,在網(wǎng)絡情況復雜又需要獲取用戶真實IP時非常有用,這篇文章主要給大家介紹了關于nginx中配置使用proxy?protocol協(xié)議的相關資料,需要的朋友可以參考下2022-04-04國外著名論壇程序IPB(Invision Power Board)在nginx下的配置示例
這篇文章主要介紹了國外著名論壇程序IPB(Invision Power Board)在nginx下的配置示例,使用fastcgi配置模式,需要的朋友可以參考下2014-07-07nginx提示:500 Internal Server Error錯誤解決辦法
這篇文章主要介紹了 nginx提示:500 Internal Server Error錯誤解決辦法的相關資料,這里提供了解決該問題的詳細步驟,希望能幫助到大家,需要的朋友可以參考下2017-08-08Nginx代理Vue項目出現(xiàn)Invalid Host header問題及解決
在使用Nginx的upstream對Vue項目進行負載均衡時,如果代理地址無法訪問目標地址且頁面報錯InvalidHostheader(無效主機頭),可能是由于Vue項目的主機檢查配置導致的,解決方法是在Vue項目的webpack.dev.js文件中的devServer下添加disableHostCheck:true,跳過主機檢查2024-12-12