新聞資訊  快訊  焦點  財經  政策  社會
互 聯 網   電商  金融  數據  計算  技巧
生活百科  科技  職場  健康  法律  汽車
手機百科  知識  軟件  修理  測評  微信
軟件技術  應用  系統  圖像  視頻  經驗
硬件技術  知識  技術  測評  選購  維修
網絡技術  硬件  軟件  設置  安全  技術
程序開發  語言  移動  數據  開源  百科
安全防護  資訊  黑客  木馬  病毒  移動
站長技術  搜索  SEO  推廣  媒體  移動
財經百科  股票  知識  理財  財務  金融
教育考試  育兒  小學  高考  考研  留學
您當前的位置:首頁 > IT百科 > 程序開發 > 語言 > JAVA

Java正確獲取客戶端真實IP方法整理——附教程

時間:2019-06-17 14:49:13  來源:  作者:
干貨:<a href=http://www.encras.tw/it/cxkf/yy/JAVA/ target=_blank class=infotextkey>JAVA</a>正確獲取客戶端真實IP方法整理——附教程

 

在JSP里,獲取客戶端的IP地址的方法是:request.getRemoteAddr(),這種方法在大部分情況下都是有效的。但是在通過了Apache,Squid等反向代理軟件就不能獲取到客戶端的真實IP地址了。

如果使用了反向代理軟件,將http://192.168.1.110:2046/的URL反向代理為http://www.abc.com/的URL時,用request.getRemoteAddr()方法獲取的IP地址是:127.0.0.1或192.168.1.110,而并不是客戶端的真實IP。

經過代理以后,由于在客戶端和服務之間增加了中間層,因此服務器無法直接拿到客戶端的IP,服務器端應用也無法直接通過轉發請求的地址返回給客戶端。但是在轉發請求的HTTP頭信息中,增加了X-FORWARDED-FOR信息。用以跟蹤原有的客戶端IP地址和原來客戶端請求的服務器地址。

當我們訪問http://www.abc.com/index.jsp/時,其實并不是我們瀏覽器真正訪問到了服務器上的index.jsp文件,而是先由代理服務器去訪問http://192.168.1.110:2046/index.jsp,代理服務器再將訪問到的結果返回給我們的瀏覽器,因為是代理服務器去訪問index.jsp的,所以index.jsp中通過request.getRemoteAddr()的方法獲取的IP實際上是代理服務器的地址,并不是客戶端的IP地址。

外界流傳的JAVA/php服務器端獲取客戶端IP都是這么取的:

偽代碼:

1)ip = request.getHeader("X-FORWARDED-FOR ")

2)如果該值為空或數組長度為0或等于"unknown",那么:

ip = request.getHeader("Proxy-Client-IP")

3)如果該值為空或數組長度為0或等于"unknown",那么:

ip = request.getHeader("WL-Proxy-Client-IP")

4)如果該值為空或數組長度為0或等于"unknown",那么:

ip = request.getHeader("HTTPCLIENTIP")

5)如果該值為空或數組長度為0或等于"unknown",那么:

ip = request.getHeader("X-Real-IP")

6)如果該值為空或數組長度為0或等于"unknown",那么:

ip = request.getRemoteAddr ()

先說說這些請求頭的意思

  • X-Forwarded-For

 

這是一個 Squid 開發的字段,只有在通過了HTTP代理或者負載均衡服務器時才會添加該項。

格式為X-Forwarded-For:client1,proxy1,proxy2,一般情況下,第一個ip為客戶端真實ip,后面的為經過的代理服務器ip。現在大部分的代理都會加上這個請求頭。

  • Proxy-Client-IP/WL- Proxy-Client-IP

 

這個一般是經過apache http服務器的請求才會有,用apache http做代理時一般會加上Proxy-Client-IP請求頭,而WL-Proxy-Client-IP是他的weblogic插件加上的頭。

  • HTTPCLIENTIP

 

有些代理服務器會加上此請求頭。

  • X-Real-IP Nginx代理一般會加上此請求頭。

 

下面是一個參考獲取客戶端IP地址的方法:

public
 
static
 
String
 getIpAddress
(
HttpservletRequest
 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
.
getRemoteAddr
();
 
}
 
if
 
(
ip
.
contains
(
","
))
 
{
 
return
 ip
.
split
(
","
)[
0
];
 
}
 
else
 
{
 
return
 ip
;
 
}
}

如果使用的是Druid連接池,可以參考使用:com.alibaba.druid.util.DruidWebUtils#getRemoteAddr方法,但這個是經過多級代理的IP地址,需要自己處理下獲取第一個。

有幾點要注意

  1. 這些請求頭都不是http協議里的標準請求頭,也就是說這個是各個代理服務器自己規定的表示客戶端地址的請求頭。如果哪天有一個代理服務器軟件用oooo-client-ip這個請求頭代表客戶端請求,那上面的代碼就不行了。
  2. 這些請求頭不是代理服務器一定會帶上的,網絡上的很多匿名代理就沒有這些請求頭,所以獲取到的客戶端ip不一定是真實的客戶端ip。代理服務器一般都可以自定義請求頭設置。
  3. 即使請求經過的代理都會按自己的規范附上代理請求頭,上面的代碼也不能確保獲得的一定是客戶端ip。不同的網絡架構,判斷請求頭的順序是不一樣的。
  4. 最重要的一點,請求頭都是可以偽造的。如果一些對客戶端校驗較嚴格的應用(比如投票)要獲取客戶端ip,應該直接使用ip=request.getRemoteAddr(),雖然獲取到的可能是代理的ip而不是客戶端的ip,但這個獲取到的ip基本上是不可能偽造的,也就杜絕了刷票的可能。(有分析說arp欺騙+syn有可能偽造此ip,如果真的可以,這是所有基于TCP協議都存在的漏洞),這個ip是tcp連接里的ip。


Tags:Java   點擊:()  評論:()
聲明:本站部分內容來自互聯網,內容觀點僅代表作者本人,如有任何版權侵犯請與我們聯系,我們將立即刪除。
▌相關評論
發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
▌相關推薦
1.關于面向對象的概念a. 類 class :在js中就是構造函數*在傳統的買你想對象語言中,使用一個叫做類的東西定義模板,然后使用模板創建對象。*在構造方法中也具有類似的功能,因此稱...【詳細內容】
2019-10-10   Java  點擊:(1)  評論:(0)  加入收藏
Scanner識別庫,識別器可選擇,這里有你常用的二維碼/條碼識別,還有你可能用到的身份證、銀行卡識別,如果沒有你想要的,可以自定義識別器。該庫只識別掃描框內的圖像,識別速率上大大...【詳細內容】
2019-10-10   Java  點擊:(1)  評論:(0)  加入收藏
在2011年7月28日,jdk1.7被正式發布。他的一個最大的亮點就是將原來的NIO類庫生成到了NIO2.0,也被叫做AIO。這篇文章將通過案例對AIO進行一個講解。一、IO的演進在jdk1.4之前,ja...【詳細內容】
2019-10-10   Java  點擊:(1)  評論:(0)  加入收藏
在Java中,兩個Integer類型的數,都為127時,用雙等判斷是否相等時,返回true。如圖: 但是,當大于127時,比如加了1,當128時,再這樣判斷,就會失敗。如圖: 直接說原因:雙等用在對象上時,判斷的...【詳細內容】
2019-10-10   Java  點擊:(1)  評論:(0)  加入收藏
前言在談CAS算法時,我們先來了解一下無鎖的概念。無鎖分為以下兩大派系: 對于樂觀派系而言,它們認為事情總會往好的方向去發展,總是認為壞的情況發生概率特別小,可以無所顧忌的做...【詳細內容】
2019-10-10   Java  點擊:(1)  評論:(0)  加入收藏
初始化一個類,生成一個實例的時候;newInstance() 和 new 有什么區別?用newInstance與用new是區別的,區別在于創建對象的方式不一樣,前者是使用類加載機制,那么為什么會有兩種創建...【詳細內容】
2019-10-10   Java  點擊:(1)  評論:(0)  加入收藏
創建線程,是多線程編程中最基本的操作,彤哥總結了一下,大概有8種創建線程的方式,你知道嗎?...【詳細內容】
2019-10-10   Java  點擊:(1)  評論:(0)  加入收藏
1. 前言對于Flink中各個組件(JobMaster、TaskManager、Dispatcher等),其底層RPC框架基于Akka實現,本文著重分析Flink中的Rpc框架實現機制及梳理其通信流程。 2. Akka介紹由于Fli...【詳細內容】
2019-10-09   Java  點擊:(8)  評論:(0)  加入收藏
Java中的return語句總是和方法有密切關系,return語句總是用在方法中,有兩個作用,一個是返回方法指定類型的值(這個值總是確定的),一個是結束方法的執行(僅僅一個return語句)。在...【詳細內容】
2019-10-09   Java  點擊:(8)  評論:(0)  加入收藏
大家經常瀏覽一些網站時候會彈出在線聊天窗口,點擊后可以和客服人員聊天,非常方便,之前也做過一款簡單的在線聊天工具,下面就說說在線聊天通訊的主要幾種技術手段。1、Ajax在htm...【詳細內容】
2019-10-09   Java  點擊:(4)  評論:(0)  加入收藏
java中基本類型中,long和double的長度都是8個字節,32位(4字節)處理器對其讀寫操作無法一次完成,那么,JVM,long和double是原子性的嗎?...【詳細內容】
2019-10-08   Java  點擊:(5)  評論:(0)  加入收藏
引言js的異步操作,已經是一個老生常談的話題,關于這個話題的文章隨便google一下都可以看到一大堆。那么為什么我還要寫這篇東西呢?在最近的工作中,為了編寫一套相對比較復雜的插...【詳細內容】
2019-10-08   Java  點擊:(5)  評論:(0)  加入收藏
你可能還記得,Liskov 代換原則是關于承諾和契約的規則。但具體是怎樣的承諾呢?為了確保 subtype(子類型)的安全性,意味著必須保證可以合理地從超類型推導出 subtype,而且這個過程...【詳細內容】
2019-10-08   Java  點擊:(5)  評論:(0)  加入收藏
McGovernTheory在StackOverflow提了這樣一個問題:?Java虛擬機最多支持多少個線程?跟虛擬機開發商有關么?跟操作系統呢?還有其他的因素嗎?...【詳細內容】
2019-10-08   Java  點擊:(5)  評論:(0)  加入收藏
我們平常的生活工作中,百度、谷歌這些搜索網站已經成為了我們受教解惑的學校,俗話說得好,“有問題找度娘”。那么百度是如何在海量數據中找到自己需要的數據呢?為什么它搜索的速...【詳細內容】
2019-10-08   Java  點擊:(7)  評論:(0)  加入收藏
今天一位同事問我關于本文標題描述的功能如何實現,Jerry在網上隨便搜了一下,類似的例子非常多,這里隨便找了一個例子做了精簡,方便Jerry以后重用。 其實之前Jerry的文章 只要200...【詳細內容】
2019-10-08   Java  點擊:(4)  評論:(0)  加入收藏
如何創建和初始化一個HashMap,看似簡單的問題,其實真的挺簡單的,但我們希望從多種方法中,選擇一個最簡潔方便、可讀性也高的方法。 代碼塊初始化可以使用靜態代碼塊和非靜態代碼...【詳細內容】
2019-09-29   Java  點擊:(11)  評論:(0)  加入收藏
前言明代王陽明先生在《傳習錄》談為學之道時說:私欲日生,如地上塵,一日不掃,便又有一層。著實用功,便見道無終窮,愈探愈深,必使精白無一毫不徹方可。代碼中的"壞味道",如"私欲"如"...【詳細內容】
2019-09-29   Java  點擊:(11)  評論:(0)  加入收藏
一、數據庫架構原則 高可用 高性能 一致性 擴展性二、常見的架構方案方案一:主備架構,只有主庫提供讀寫服務,備庫冗余作故障轉移用 jdbc:mysql://vip:3306/xxdb1、高可用分析:高...【詳細內容】
2019-09-27   Java  點擊:(6)  評論:(0)  加入收藏
人與人之間通過交流構成了這個豐富多彩的世界,在計算機中,通過即時通信工具傳遞信息為我么的生活增添了很多樂趣也提供了很多遍歷,而在java線程的世界里,線程之間的通信,可以極大...【詳細內容】
2019-09-27   Java  點擊:(4)  評論:(0)  加入收藏
推薦資訊
相關文章
欄目更新
欄目熱門
31选7开奖11185