Java面試題-如何獲取客戶端真實IP
在進行一些小遊戲開發時,我們經常比較關注的一個功能便是分享。針對分享,我們希望能根據各個城市或者地區,能有不同的分享文案,辨識地區的功能如果由伺服器來完成的話,我們就需要知道客戶端的真實IP。今天 陝西優就業小編就和大家一起來看看伺服器是如何獲取到客戶端的真實IP的。
nginx配置
首先,一個請求肯定是可以分為請求頭和請求體的,而我們客戶端的IP地址資訊一般都是儲存在請求頭裡的。如果你的伺服器有用Nginx做負載均衡的話,你需要在你的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 }
1. X-Real-IP
在《實戰nginx》中,有這麼一句話:
經過反向代理後,由於在客戶端和web伺服器之間增加了中間層,因此web伺服器無法直接拿到客戶端的ip,透過$remote_addr變數拿到的將是反向代理伺服器的ip地址。
這句話的意思是說,當你使用了nginx反向伺服器後,在web端使用request.getRemoteAddr()(本質上就是獲取$remote_addr),取得的是nginx的地址,即$remote_addr變數中封裝的是nginx的地址,當然是沒法獲得使用者的真實ip的。但是,nginx是可以獲得使用者的真實ip的,也就是說nginx使用$remote_addr變數時獲得的是使用者的真實ip,如果我們想要在web端獲得使用者的真實ip,就必須在nginx裡作一個賦值操作,即我在上面的配置:
proxy_set_header X-Real-IP $remote_addr;
2. X-Forwarded-For
X-Forwarded-For變數,這是一個squid開發的,用於識別透過HTTP代理或負載平衡器原始IP一個連線到Web伺服器的客戶機地址的非rfc標準,如果有做X-Forwarded-For設定的話,每次經過proxy轉發都會有記錄,格式就是client1,proxy1,proxy2以逗號隔開各個地址,由於它是非rfc標準,所以預設是沒有的,需要強制新增。在預設情況下經過proxy轉發的請求,在後端看來遠端地址都是proxy端的ip 。也就是說在預設情況下我們使用request.getAttribute("X-Forwarded-For")獲取不到使用者的ip,如果我們想要透過這個變數獲得使用者的ip,我們需要自己在nginx新增配置:
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
意思是增加一個$proxy_add_x_forwarded_for到X-Forwarded-For裡去,注意是增加,而不是覆蓋,當然由於預設的X-Forwarded-For值是空的,所以我們總感覺X-Forwarded-For的值就等於$proxy_add_x_forwarded_for的值,實際上當你搭建兩臺nginx在不同的ip上,並且都使用了這段配置,那你會發現在web伺服器端透過request.getAttribute("X-Forwarded-For")獲得的將會是客戶端ip和第一臺nginx的ip。
3. 那麼$proxy_add_x_forwarded_for又是什麼?
$proxy_add_x_forwarded_for變數包含客戶端請求頭中的X-Forwarded-For與$remote_addr兩部分,他們之間用逗號分開。
舉個例子,有一個web應用,在它之前透過了兩個nginx轉發,即使用者訪問該web透過兩臺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的值是使用者的ip,於是賦值以後,X-Forwarded-For變數的值就是使用者的真實的ip地址了。
到了第二臺nginx,使用:
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
現在的$proxy_add_x_forwarded_for變數,X-Forwarded-For部分包含的是使用者的真實ip,$remote_addr部分的值是上一臺nginx的ip地址,於是透過這個賦值以後現在的X-Forwarded-For的值就變成了“使用者的真實ip,第一臺nginx的ip”,這樣就清楚了吧。
伺服器獲取真實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)) { //多次反向代理後會有多個ip值,第一個ip才是真實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; }
我們來看看各個請求頭的含義:
X-Real-IP:nginx代理一般會加上此請求頭。
X-FORWARDED-FOR:這是一個Squid開發的欄位,只有在透過了HTTP代理或者負載均衡伺服器時才會新增該項。
Proxy-Client-IP 和 WL-Proxy-Client-IP:這個一般是經過apache http伺服器的請求才會有,用apache http做代理時一般會加上Proxy-Client-IP請求頭,而WL-Proxy-Client-IP是它的weblogic外掛加上的頭。
HTTPCLIENTIP
有些代理伺服器會加上此請求頭。在網上搜了一下,有一個說法是:
這是普通的 http header,偽造起來很容易,不要輕易信任使用者輸入。 curl -H 'client-ip: 8.8.8.8' lidian.club/phpinfo.php | grep _SERVER 你就能看到 _SERVER["HTTP_CLIENT_IP"] 了。 client-ip 和 client-host 是在 NAPT 還沒普及的年代,企業內網假設的 http 透明代理,傳給伺服器的 header,只有極少數廠家用過,從來不是標準,也從來沒成為過事實標準。 (大家最熟悉的事實標準就是 x-forwarded-for) 後來出現的 web proxy 也沒見用過這個 header。 TCP/IP Illustrated Vol 3 沒有講過這個 header,網上的傳言不可信。 可考的最早痕跡出現在2005年,日本一部 Perl/CGI 秘籍(9784798010779,270頁)透過 client-ip 與 via 兩個 header 遮蔽代理使用者訪問。
簡稱XFF頭,它代表客戶端,也就是HTTP的請求端真實的IP,只有在透過了HTTP 代理(比如APACHE代理)或者負載均衡伺服器時才會新增該項。它不是RFC中定義的標準請求頭資訊,在squid快取代理伺服器開發文件中可以找到該項的詳細介紹。如果有該條資訊, 說明您使用了代理伺服器,地址就是後面的數值。可以偽造。標準格式如下:X-Forwarded-For: client1, proxy1, proxy2
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/69902581/viewspace-2662862/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- java 獲取客戶端真實ipJava客戶端
- 獲取客戶端真實IP客戶端
- .net 獲取客戶端真實ip客戶端
- Nginx 反向代理後如何獲取真實客戶端 IPNginx客戶端
- 伺服器獲取真實客戶端 IP伺服器客戶端
- nginx多級代理下如何獲取客戶端真實IPNginx客戶端
- java獲取客戶端ip和macJava客戶端Mac
- nginx反向代理獲取客戶端的真實IP和域名Nginx客戶端
- 在容器服務中獲取客戶端真實源 IP客戶端
- pomelo獲取客戶端IP客戶端
- ABP vNext 審計日誌獲取真實客戶端IP客戶端
- java web 通過request獲取客戶端IPJavaWeb客戶端
- c# 獲取客戶端IPC#客戶端
- 服務端如何獲取客戶端請求IP地址服務端客戶端
- nginx後端獲取真實ipNginx後端
- JSF/JAVA 根據IP獲取客戶端Mac地址JSJava客戶端Mac
- 【Nginx】如何獲取客戶端真實IP、域名、協議、埠?看這一篇就夠了!Nginx客戶端協議
- Django透過request獲取客戶端IPDjango客戶端
- 如何獲取終端使用者的真實ip
- 一次獲取客戶端 IP 記錄客戶端
- Java/JSP獲得客戶端網路卡MAC地址的三種方法解析(附:獲得真實IP)JavaJS客戶端Mac
- ASP.NET獲取客戶端IP及MAC地址ASP.NET客戶端Mac
- JS獲取客戶端IP地址與機器名JS客戶端
- 在SelfHost專案中獲取客戶端IP地址客戶端
- 獲取真實IP地址
- nginx設定反向代理怎麼獲取客戶端的真實IP和域名以供日誌分析Nginx客戶端
- 獲取SQL Server中連線的客戶端IP地址SQLServer客戶端
- Silverlight中利用WCF獲取客戶端IP客戶端
- 在OwinSelfHost專案中獲取客戶端IP地址客戶端
- 獲取客戶端Mac地址客戶端Mac
- Nginx前端設定反向代理,後端Apache如何獲取訪客的真實IP,結合PHPNginx前端後端ApachePHP
- 從刷票瞭解如何獲得客戶端IP客戶端
- tomcat採集阿里雲slb真實客戶端ip🫚Tomcat阿里客戶端
- Spring 客戶端 IP 地址獲取及儲存細節Spring客戶端
- 阿里雲CDN + nginx多級代理獲取客戶端IP阿里Nginx客戶端
- PHP獲得真實客戶端的真實IPREMOTE_ADDR,HTTP_CLIENT_IP,HTTP_X_FORWARDED_FORPHP客戶端REMHTTPclientForward
- Apapche獲取真實IP地址方法
- Nacos - 客戶端例項列表獲取客戶端