国产成人精品无码青草_亚洲国产美女精品久久久久∴_欧美人与鲁交大毛片免费_国产果冻豆传媒麻婆精东

18143453325 在線咨詢 在線咨詢
18143453325 在線咨詢
所在位置: 首頁 > 營(yíng)銷資訊 > 建站知識(shí) > 【Nginx】如何獲取客戶端真實(shí)IP、域名、協(xié)議、端口?看這一篇就夠了!

【Nginx】如何獲取客戶端真實(shí)IP、域名、協(xié)議、端口?看這一篇就夠了!

時(shí)間:2023-01-30 16:40:01 | 來源:建站知識(shí)

時(shí)間:2023-01-30 16:40:01 來源:建站知識(shí)

寫在前面

Nginx最為最受歡迎的反向代理和負(fù)載均衡服務(wù)器,被廣泛的應(yīng)用于互聯(lián)網(wǎng)項(xiàng)目中。這不僅僅是因?yàn)镹ginx本身比較輕量,更多的是得益于Nginx的高性能特性,以及支持插件化開發(fā),為此,很多開發(fā)者或者公司基于Nginx開發(fā)出了眾多的高性能插件。使用者可以根據(jù)自身的需求來為Nginx指定某款插件以增強(qiáng)Nginx在某種特定場(chǎng)景下的功能或者提升Nginx在某種特定場(chǎng)景下的性能。

Nginx獲取客戶端信息

注意:本文中的客戶端信息指的是:客戶端真實(shí)IP、域名、協(xié)議、端口。

Nginx反向代理后,Servlet應(yīng)用通過request.getRemoteAddr()取到的IP是Nginx的IP地址,并非客戶端真實(shí)IP,通過request.getRequestURL()獲取的域名、協(xié)議、端口都是Nginx訪問Web應(yīng)用時(shí)的域名、協(xié)議、端口,而非客戶端瀏覽器地址欄上的真實(shí)域名、協(xié)議、端口。

直接獲取信息存在哪些問題?

例如在某一臺(tái)IP為192.168.1.100的服務(wù)器上,Jetty或者Tomcat端口號(hào)為8080,Nginx端口號(hào)80,Nginx反向代理8080端口:

server { listen 80; location / { proxy_pass http://127.0.0.1:8080; # 反向代理應(yīng)用服務(wù)器HTTP地址 }}在另一臺(tái)機(jī)器上用瀏覽器打開http://192.168.1.100/test訪問某個(gè)Servlet應(yīng)用,獲取客戶端IP和URL:

System.out.println("RemoteAddr: " + request.getRemoteAddr());System.out.println("URL: " + request.getRequestURL().toString());打印的結(jié)果信息如下:

RemoteAddr: 127.0.0.1URL: http://127.0.0.1:8080/test可以發(fā)現(xiàn),Servlet程序獲取到的客戶端IP是Nginx的IP而非瀏覽器所在機(jī)器的IP,獲取到的URL是Nginx proxy_pass配置的URL組成的地址,而非瀏覽器地址欄上的真實(shí)地址。如果將Nginx用作https服務(wù)器反向代理后端的http服務(wù),那么request.getRequestURL()獲取的URL是http前綴的而非https前綴,無法獲取到瀏覽器地址欄的真實(shí)協(xié)議。如果此時(shí)將request.getRequestURL()獲取得到的URL用作拼接Redirect地址,就會(huì)出現(xiàn)跳轉(zhuǎn)到錯(cuò)誤的地址,這也是Nginx反向代理時(shí)經(jīng)常出現(xiàn)的一個(gè)問題。

如何解決這些問題?

既然直接使用Nginx獲取客戶端信息存在問題,那我們?cè)撊绾谓鉀Q這個(gè)問題呢?

我們整體上需要從兩個(gè)方面來解決這些問題:

(1)由于Nginx是代理服務(wù)器,所有客戶端請(qǐng)求都從Nginx轉(zhuǎn)發(fā)到Jetty/Tomcat,如果Nginx不把客戶端真實(shí)IP、域名、協(xié)議、端口告訴Jetty/Tomcat,那么Jetty/Tomcat應(yīng)用永遠(yuǎn)不會(huì)知道這些信息,所以需要Nginx配置一些HTTP Header來將這些信息告訴被代理的Jetty/Tomcat;

(2)Jetty/Tomcat這一端,不能再獲取直接和它連接的客戶端(也就是Nginx)的信息,而是要從Nginx傳遞過來的HTTP Header中獲取客戶端信息。

具體實(shí)踐

配置nginx

首先,我們需要在Nginx的配置文件nginx.conf中添加如下配置。

proxy_set_header Host $http_host;proxy_set_header X-Real-IP $remote_addr;proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;proxy_set_header X-Forwarded-Proto $scheme;各參數(shù)的含義如下所示。

此時(shí),再試一下request.getRemoteAddr()request.getRequestURL()的輸出結(jié)果:

RemoteAddr: 127.0.0.1URL: http://192.168.1.100/test可以發(fā)現(xiàn)URL好像已經(jīng)沒問題了,但是IP還是本地的IP而非真實(shí)客戶端IP。但是如果是用Nginx作為https服務(wù)器反向代理到http服務(wù)器,會(huì)發(fā)現(xiàn)瀏覽器地址欄是https前綴但是request.getRequestURL()獲取到的URL還是http前綴,也就是僅僅配置Nginx還不能徹底解決問題。

通過Java方法獲取客戶端信息

僅僅配置Nginx不能徹底解決問題,那如何才能解決這個(gè)問題呢?一種解決方式就是通過Java方法獲取客戶端信息,例如下面的Java方法。

/*** * 獲取客戶端IP地址;這里通過了Nginx獲取;X-Real-IP */public static String getClientIP(HttpServletRequest request) { String fromSource = "X-Real-IP"; String ip = request.getHeader("X-Real-IP"); if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) { ip = request.getHeader("X-Forwarded-For"); fromSource = "X-Forwarded-For"; } if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) { ip = request.getHeader("Proxy-Client-IP"); fromSource = "Proxy-Client-IP"; } if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) { ip = request.getHeader("WL-Proxy-Client-IP"); fromSource = "WL-Proxy-Client-IP"; } if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) { ip = request.getRemoteAddr(); fromSource = "request.getRemoteAddr"; } return ip;}這種方式雖然能夠獲取客戶端的IP地址,但是我總感覺這種方式不太友好,因?yàn)榧热籗ervlet API提供了request.getRemoteAddr()方法獲取客戶端IP,那么無論有沒有用反向代理對(duì)于代碼編寫者來說應(yīng)該是透明的。

接下來,我就分別針對(duì)Jetty服務(wù)器和Tomcat服務(wù)器為大家介紹下如何進(jìn)行配置才能更加友好的獲取客戶端信息。

Jetty服務(wù)器

在Jetty服務(wù)器的jetty.xml文件中,找到httpConfig,加入配置:

<New id="httpConfig" class="org.eclipse.jetty.server.HttpConfiguration"> ... <Call name="addCustomizer"> <Arg><New class="org.eclipse.jetty.server.ForwardedRequestCustomizer"/></Arg> </Call></New>重新啟動(dòng)Jetty,再用瀏覽器打開http://192.168.1.100/test測(cè)試,結(jié)果:

RemoteAddr: 192.168.1.100URL: http://192.168.1.100/test此時(shí)可發(fā)現(xiàn)通過request.getRemoteAddr()獲取到的IP不再是127.0.0.1而是客戶端真實(shí)IP,request.getRequestURL()獲取的URL也是瀏覽器上的真實(shí)URL,如果Nginx作為https代理,request.getRequestURL()的前綴也會(huì)是https。

另外,Jetty將這個(gè)功能封裝成一個(gè)模塊:http-forwarded。如果不想改jetty.xml配置文件的話,也可以啟用http-forwarded模塊來實(shí)現(xiàn)。

例如可以通過命令行啟動(dòng)Jetty:

java -jar start.jar --module=http-forwarded更多Jetty如何啟用模塊的相關(guān)資料可以參考:http://www.eclipse.org/jetty/documentation/current/startup.html

Tomcat

和Jetty類似,如果使用Tomcat作為應(yīng)用服務(wù)器,可以通過配置Tomcat的server.xml文件,在Host元素內(nèi)最后加入:

<Valve className="org.apache.catalina.valves.RemoteIpValve" />好了,咱們今天就聊到這兒吧!別忘了給個(gè)在看和轉(zhuǎn)發(fā),讓更多的人看到,一起學(xué)習(xí)一起進(jìn)步!!

造個(gè)輪子
我們經(jīng)常說不要重復(fù)造輪子。為了開發(fā)效率,可以不造輪子,但是必須具備造輪子的能力。建議造一個(gè)簡(jiǎn)單的MQ,你能用到通信協(xié)議、設(shè)計(jì)模式、隊(duì)列等許多知識(shí)。在造輪子的過程中,你會(huì)頻繁的翻閱各種手冊(cè)或者博客,這就是用輸出倒逼輸入。


上面是我自己整理的一些學(xué)習(xí)資料,還有一些大公司面試題,比較干貨,需要的朋友可以私信我回復(fù)‘資料’,或者點(diǎn)下方文檔我可以免費(fèi)分享。






關(guān)鍵詞:協(xié)議,獲取,真實(shí)

74
73
25
news

版權(quán)所有? 億企邦 1997-2025 保留一切法律許可權(quán)利。

為了最佳展示效果,本站不支持IE9及以下版本的瀏覽器,建議您使用谷歌Chrome瀏覽器。 點(diǎn)擊下載Chrome瀏覽器
關(guān)閉