- 資訊首頁(yè) > 開(kāi)發(fā)技術(shù) > 編程語(yǔ)言 >
- Java中如何獲取客戶(hù)端真實(shí)IP
今天就跟大家聊聊有關(guān)Java中如何獲取客戶(hù)端真實(shí)IP,可能很多人都不太了解,為了讓大家更加了解,小編給大家總結了以下內容,希望大家根據這篇文章可以有所收獲。
nginx配置
首先,一個(gè)請求肯定是可以分為請求頭和請求體的,而我們客戶(hù)端的IP地址信息一般都是存儲在請求頭里的。如果你的有用Nginx做的話(huà),你需要在你的location里面配置X-Real-IP和X-Forwarded-For請求頭:
location ^~ /your-service/ { proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_pass http://localhost:60000/your-service/; }
1. X-Real-IP
在《實(shí)戰nginx》中,有這么一句話(huà):
經(jīng)過(guò)反向代理后,由于在客戶(hù)端和web服務(wù)器之間增加了中間層,因此web服務(wù)器無(wú)法直接拿到客戶(hù)端的ip,通過(guò)$remote_addr變量拿到的將是反向代理服務(wù)器的ip地址。
這句話(huà)的意思是說(shuō),當你使用了nginx反向服務(wù)器后,在web端使用request.getRemoteAddr()(本質(zhì)上就是獲取$remote_addr),取得的是nginx的地址,即$remote_addr變量中封裝的是nginx的地址,當然是沒(méi)法獲得用戶(hù)的真實(shí)ip的。但是,nginx是可以獲得用戶(hù)的真實(shí)ip的,也就是說(shuō)nginx使用$remote_addr變量時(shí)獲得的是用戶(hù)的真實(shí)ip,如果我們想要在web端獲得用戶(hù)的真實(shí)ip,就必須在nginx里作一個(gè)賦值操作,即我在上面的配置:
proxy_set_header X-Real-IP $remote_addr;
2. X-Forwarded-For
X-Forwarded-For變量,這是一個(gè)squid開(kāi)發(fā)的,用于識別通過(guò)HTTP代理或負載平衡器原始IP一個(gè)連接到Web服務(wù)器的客戶(hù)機地址的非rfc標準,如果有做X-Forwarded-For設置的話(huà),每次經(jīng)過(guò)proxy轉發(fā)都會(huì )有記錄,格式就是client1,proxy1,proxy2以逗號隔開(kāi)各個(gè)地址,由于它是非rfc標準,所以默認是沒(méi)有的,需要強制添加。在默認情況下經(jīng)過(guò)proxy轉發(fā)的請求,在后端看來(lái)遠程地址都是proxy端的ip 。也就是說(shuō)在默認情況下我們使用request.getAttribute("X-Forwarded-For")獲取不到用戶(hù)的ip,如果我們想要通過(guò)這個(gè)變量獲得用戶(hù)的ip,我們需要自己在nginx添加配置:
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
意思是增加一個(gè)$proxy_add_x_forwarded_for到X-Forwarded-For里去,注意是增加,而不是覆蓋,當然由于默認的X-Forwarded-For值是空的,所以我們總感覺(jué)X-Forwarded-For的值就等于$proxy_add_x_forwarded_for的值,實(shí)際上當你搭建兩臺nginx在不同的ip上,并且都使用了這段配置,那你會(huì )發(fā)現在web服務(wù)器端通過(guò)request.getAttribute("X-Forwarded-For")獲得的將會(huì )是客戶(hù)端ip和第一臺nginx的ip。
3. 那么$proxy_add_x_forwarded_for又是什么?
$proxy_add_x_forwarded_for變量包含客戶(hù)端請求頭中的X-Forwarded-For與$remote_addr兩部分,他們之間用逗號分開(kāi)。
舉個(gè)例子,有一個(gè)web應用,在它之前通過(guò)了兩個(gè)nginx轉發(fā),www.linuxidc.com即用戶(hù)訪(fǎng)問(wèn)該web通過(guò)兩臺nginx。
在第一臺nginx中,使用:
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
現在的$proxy_add_x_forwarded_for變量的X-Forwarded-For部分是空的,所以只有$remote_addr,而$remote_addr的值是用戶(hù)的ip,于是賦值以后,X-Forwarded-For變量的值就是用戶(hù)的真實(shí)的ip地址了。
到了第二臺nginx,使用:
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
現在的$proxy_add_x_forwarded_for變量,X-Forwarded-For部分包含的是用戶(hù)的真實(shí)ip,$remote_addr部分的值是上一臺nginx的ip地址,于是通過(guò)這個(gè)賦值以后現在的X-Forwarded-For的值就變成了“用戶(hù)的真實(shí)ip,第一臺nginx的ip”,這樣就清楚了吧。
服務(wù)器獲取真實(shí)IP
代碼為:
public static String getIpAddress(HttpServletRequest request) { String Xip = request.getHeader("X-Real-IP"); String XFor = request.getHeader("X-Forwarded-For"); if (!Strings.isNullOrEmpty(XFor) && !"unKnown".equalsIgnoreCase(XFor)) { //多次反向代理后會(huì )有多個(gè)ip值,第一個(gè)ip才是真實(shí)ip int index = XFor.indexOf(","); if (index != -1) { return XFor.substring(0, index); } else { return XFor; } } XFor = Xip; if (!Strings.isNullOrEmpty(XFor) && !"unKnown".equalsIgnoreCase(XFor)) { return XFor; } if (Strings.nullToEmpty(XFor).trim().isEmpty() || "unknown".equalsIgnoreCase(XFor)) { XFor = request.getHeader("Proxy-Client-IP"); } if (Strings.nullToEmpty(XFor).trim().isEmpty() || "unknown".equalsIgnoreCase(XFor)) { XFor = request.getHeader("WL-Proxy-Client-IP"); } if (Strings.nullToEmpty(XFor).trim().isEmpty() || "unknown".equalsIgnoreCase(XFor)) { XFor = request.getHeader("HTTP_CLIENT_IP"); } if (Strings.nullToEmpty(XFor).trim().isEmpty() || "unknown".equalsIgnoreCase(XFor)) { XFor = request.getHeader("HTTP_X_FORWARDED_FOR"); } if (Strings.nullToEmpty(XFor).trim().isEmpty() || "unknown".equalsIgnoreCase(XFor)) { XFor = request.getRemoteAddr(); } return XFor; }
我們來(lái)看看各個(gè)請求頭的含義:
X-Real-IP:nginx代理一般會(huì )加上此請求頭。
X-FORWARDED-FOR:這是一個(gè)Squid開(kāi)發(fā)的字段,只有在通過(guò)了HTTP代理或者負載均衡服務(wù)器時(shí)才會(huì )添加該項。
Proxy-Client-IP 和 WL-Proxy-Client-IP:這個(gè)一般是經(jīng)過(guò)apache http服務(wù)器的請求才會(huì )有,用apache http做代理時(shí)一般會(huì )加上Proxy-Client-IP請求頭,而WL-Proxy-Client-IP是它的weblogic插件加上的頭。
HTTPCLIENTIP
有些代理服務(wù)器會(huì )加上此請求頭。在網(wǎng)上搜了一下,有一個(gè)說(shuō)法是:
這是普通的 http header,偽造起來(lái)很容易,不要輕易信任用戶(hù)輸入。 curl -H 'client-ip: 8.8.8.8' lidian.club/phpinfo.php | grep _SERVER 你就能看到 _SERVER["HTTP_CLIENT_IP"] 了。 client-ip 和 client-host 是在 NAPT 還沒(méi)普及的年代,企業(yè)內網(wǎng)假設的 http 透明代理,傳給服務(wù)器的 header,只有極少數廠(chǎng)家用過(guò),從來(lái)不是標準,也從來(lái)沒(méi)成為過(guò)事實(shí)標準。 (大家最熟悉的事實(shí)標準就是 x-forwarded-for) 后來(lái)出現的 web proxy 也沒(méi)見(jiàn)用過(guò)這個(gè) header。 TCP/IP Illustrated Vol 3 沒(méi)有講過(guò)這個(gè) header,網(wǎng)上的傳言不可信。 可考的最早痕跡出現在2005年,日本一部 Perl/CGI 秘籍(9784798010779,270頁(yè))通過(guò) client-ip 與 via 兩個(gè) header 屏蔽代理用戶(hù)訪(fǎng)問(wèn)。
簡(jiǎn)稱(chēng)XFF頭,它代表客戶(hù)端,也就是HTTP的請求端真實(shí)的IP,只有在通過(guò)了HTTP 代理(比如APACHE代理)或者負載均衡服務(wù)器時(shí)才會(huì )添加該項。它不是RFC中定義的標準請求頭信息,在squid緩存代理服務(wù)器開(kāi)發(fā)文檔中可以找到該項的詳細介紹。如果有該條信息, 說(shuō)明您使用了代理服務(wù)器,地址就是后面的數值??梢詡卧?。
免責聲明:本站發(fā)布的內容(圖片、視頻和文字)以原創(chuàng )、來(lái)自本網(wǎng)站內容采集于網(wǎng)絡(luò )互聯(lián)網(wǎng)轉載等其它媒體和分享為主,內容觀(guān)點(diǎn)不代表本網(wǎng)站立場(chǎng),如侵犯了原作者的版權,請告知一經(jīng)查實(shí),將立刻刪除涉嫌侵權內容,聯(lián)系我們QQ:712375056,同時(shí)歡迎投稿傳遞力量。
Copyright ? 2009-2022 56dr.com. All Rights Reserved. 特網(wǎng)科技 特網(wǎng)云 版權所有 特網(wǎng)科技 粵ICP備16109289號
域名注冊服務(wù)機構:阿里云計算有限公司(萬(wàn)網(wǎng)) 域名服務(wù)機構:煙臺帝思普網(wǎng)絡(luò )科技有限公司(DNSPod) CDN服務(wù):阿里云計算有限公司 百度云 中國互聯(lián)網(wǎng)舉報中心 增值電信業(yè)務(wù)經(jīng)營(yíng)許可證B2
建議您使用Chrome、Firefox、Edge、IE10及以上版本和360等主流瀏覽器瀏覽本網(wǎng)站