Java獲取客戶端真實(shí)IP地址過程解析
這篇文章主要介紹了Java獲取客戶端真實(shí)IP地址過程解析,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友可以參考下
業(yè)務(wù)背景
服務(wù)器端接收客戶端請求的時候,一般需要進(jìn)行簽名驗(yàn)證,客戶端IP限定等攔截,在進(jìn)行IP限定的時候就需要獲取客戶端真實(shí)的IP。
基礎(chǔ)知識
訪問服務(wù)端的方式一般分為兩種:
未經(jīng)過代理,直接訪問服務(wù)器端;
通過多級代理,最終到達(dá)服務(wù)器端(nginx,squid,haproxy)。
客戶端請求信息都包含在HttpServletRequest中,對于第一種訪問方式可以通過getRemoteAddr()方法獲得客戶端真實(shí)IP,而另一種則行不通,但是可以通過x-forwarded-for獲得轉(zhuǎn)發(fā)后請求信息。當(dāng)客戶端請求被轉(zhuǎn)發(fā)時,IP將會追加在其后并以英文逗號隔開,例如:10.47.103.13,4.2.2.2,10.96.112.230。
請求中的參數(shù):
request.getHeader("x-forwarded-for") : 10.47.103.13,4.2.2.2,10.96.112.230 request.getHeader("X-Real-IP") : 10.47.103.13 request.getRemoteAddr():10.96.112.230
客戶端訪問經(jīng)過轉(zhuǎn)發(fā),IP將會追加在其后并以逗號隔開。最終準(zhǔn)確的客戶端信息為:
- x-forwarded-for 不為空,則為逗號前第一個IP ;
- X-Real-IP不為空,則為該IP ;
- 否則為getRemoteAddr() ;
相關(guān)請求頭的解釋:
X-Forwarded-For 記錄一個請求從客戶端出發(fā)到目標(biāo)服務(wù)器過程中經(jīng)歷的代理,或者負(fù)載平衡設(shè)備的IP。這是由緩存代理軟件 Squid 引入,用來表示 HTTP 請求端真實(shí) IP,現(xiàn)在已經(jīng)成為事實(shí)上的標(biāo)準(zhǔn),被各大 HTTP 代理、負(fù)載均衡等轉(zhuǎn)發(fā)服務(wù)廣泛使用,并被寫入 RFC 7239(Forwarded HTTP Extension)標(biāo)準(zhǔn)之中。格式為X-Forwarded-For:client1,proxy1,proxy2,一般情況下,第一個ip為客戶端真實(shí)ip,后面的為經(jīng)過的代理服務(wù)器的ip?,F(xiàn)在大部分的代理都會加上這個請求頭。
Proxy-Client-IP/WL- Proxy-Client-IP 這個一般是經(jīng)過apache http服務(wù)器的請求才會有,用apache http做代理時一般會加上Proxy-Client-IP請求頭,而WL-Proxy-Client-IP是他的weblogic插件加上的頭。
HTTP_CLIENT_IP 有些代理服務(wù)器會加上此請求頭。
X-Real-IP nginx代理一般會加上此請求頭。
獲取客戶端真實(shí)IP地址
源碼:
/** * 獲取客戶端的IP地址<br/> * 注意本地測試訪問項(xiàng)目地址時,瀏覽器請求不要用 localhost,請用本機(jī)IP;否則,取不到 IP * * @author east7 * @date 2019年12月03日 * @return String 真實(shí)IP地址 */ public static String getClientIpAddress(HttpServletRequest request) { // 獲取請求主機(jī)IP地址,如果通過代理進(jìn)來,則透過防火墻獲取真實(shí)IP地址 String headerName = "x-forwarded-for"; String ip = request.getHeader(headerName); if (null != ip && ip.length() != 0 && !"unknown".equalsIgnoreCase(ip)) { // 多次反向代理后會有多個IP值,第一個IP才是真實(shí)IP,它們按照英文逗號','分割 if (ip.indexOf(",") != -1) { ip = ip.split(",")[0]; } } if (checkIp(ip)) { headerName = "Proxy-Client-IP"; ip = request.getHeader(headerName); } if (checkIp(ip)) { headerName = "WL-Proxy-Client-IP"; ip = request.getHeader(headerName); } if (checkIp(ip)) { headerName = "HTTP_CLIENT_IP"; ip = request.getHeader(headerName); } if (checkIp(ip)) { headerName = "HTTP_X_FORWARDED_FOR"; ip = request.getHeader(headerName); } if (checkIp(ip)) { headerName = "X-Real-IP"; ip = request.getHeader(headerName); } if (checkIp(ip)) { headerName = "remote addr"; ip = request.getRemoteAddr(); // 127.0.0.1 ipv4, 0:0:0:0:0:0:0:1 ipv6 if ("127.0.0.1".equals(ip) || "0:0:0:0:0:0:0:1".equals(ip)) { //根據(jù)網(wǎng)卡取本機(jī)配置的IP InetAddress inet = null; try { inet = InetAddress.getLocalHost(); } catch (UnknownHostException e) { e.printStackTrace(); } ip = inet.getHostAddress(); } } logger.info("getClientIp IP is " + ip + ", headerName = " + headerName); return ip; } private static boolean checkIp(String ip) { if (null == ip || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) { return true; } return false; }
以上就是本文的全部內(nèi)容,希望對大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
解決ApplicationContext獲取不到Bean的問題
這篇文章主要介紹了解決ApplicationContext獲取不到Bean的問題,具有很好的參考價值,希望對大家有所幫助,如有錯誤或未考慮完全的地方,望不吝賜教2024-06-06Spring XML Schema擴(kuò)展機(jī)制的使用示例
所謂整合,即在Spring的框架下進(jìn)行擴(kuò)展,讓框架能無縫的與Spring工程配合使用。Spring設(shè)計(jì)了良好的擴(kuò)展的機(jī)制,本文將對Spring的擴(kuò)展方法及原理進(jìn)行簡單介紹。2021-05-05SpringBoot實(shí)現(xiàn)微信及QQ綁定登錄的示例代碼
本文主要介紹了SpringBoot實(shí)現(xiàn)微信及QQ綁定登錄的示例代碼,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2023-07-07關(guān)于SpringCloud中Ribbon的7種負(fù)載均衡策略解析
這篇文章主要介紹了關(guān)于SpringCloud中Ribbon的7種負(fù)載均衡策略解析,服務(wù)端負(fù)載均衡器的問題是,它提供了更強(qiáng)的流量控制權(quán),但無法滿足不同的消費(fèi)者希望使用不同負(fù)載均衡策略的需求,而使用不同負(fù)載均衡策略的場景確實(shí)是存在的,需要的朋友可以參考下2023-07-07淺談Spring Batch在大型企業(yè)中的最佳實(shí)踐
本篇文章主要介紹了淺談Spring Batch在大型企業(yè)中的最佳實(shí)踐,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2017-11-11如何用匿名內(nèi)部類實(shí)現(xiàn) Java 同步回調(diào)
這篇文章主要介紹了如何用匿名內(nèi)部類實(shí)現(xiàn) Java 同步回調(diào),幫助大家更好的理解和學(xué)習(xí)Java,感興趣的朋友可以了解下2020-10-10springmvc實(shí)現(xiàn)自定義類型轉(zhuǎn)換器示例
本篇文章主要介紹了springmvc實(shí)現(xiàn)自定義類型轉(zhuǎn)換器示例,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2017-02-02