作者:蔡永吉
來源:https://blog.csdn.net/takeurhand/article/details/52512200
想必大家對這段代碼並不陌生:
是的,你搜索到的「java獲取真實IP位址」大多都是如此。但是,以上代碼真
的對嗎?
那麼我們看一下具體的代碼。如上,判斷ip地址的優先級是
"x-forwarded-for">
"Proxy-Client-IP">
"WL-Proxy-Client-IP">
request.getRemoteAddr()
其中帶引號的都是從header中獲取的。
等等!我們都知道header中的值是可以更改的。比如:
代碼出自:https://github.com/caiyongji/vote-2.0/blob/master/Vote-2.0.js
其中headers屬性X-Forwarded-For,WL-Proxy-Client-IP不就是被更改了嗎?
那麼,為什麼會有這個版本的「java獲取真實IP位址」的方法呢?並且搜尋引擎所能檢索到的結果大多都是這一個?
打個比方說,如果這個解決辦法是一本秘籍的話,那麼,我們找到的只是「java獲取真實IP位址」殘卷。
而剩下的部分在這裡:
#Nginx 設置
location ~ ^/static {
proxy_pass ....;
proxy_set_header X-Forward-For $remote_addr ;
}
這段配置是在前端Nginx反向代理上的(其他反向代理請自行搜索),這段配置
作的事情是將X-Forward-For替換為remote_addr,再將X-Forward-For在內網
各伺服器間安全傳輸。
這裡我再針對TCP/IP多做一些解釋,眾所周知TCP/IP建立連接時需要三次握手的,並且,只有知道了client端請求的IP位址,server端的數據才能返回給client,所以client想要獲取到數據就必須提供真實的IP(DDOS攻擊除外),而request.getRemoteAddr()獲取的就是用戶最真實的IP。
那麼為什麼不直接使用使用request.getRemoteAddr()這個方法呢?
如果沒有反向代理的話當然可行。但是出於安全原因,現在大多數的服務都使用代理伺服器(如Nginx,代理伺服器可以理解為用戶和伺服器之間的中介,雙方都可信任。),而用戶對代理伺服器發起的HTTP請求,代理伺服器對服務集群中的真實部署的對應服務進行「二次請求」,所以最終獲取的IP是代理伺服器在內網中的ip地址,如192.168.xx.xx/10.xx.xx.xx等等。
所以在使用了反向代理的情況下,request.getRemoteAddr()獲取的是反響代理在內網中的ip地址。所以在反向代理中將X-Forward-For替換為remote_addr,即,真實的IP位址。之後在內網中獲取的x-forwarded-for便是真實的ip地址了。
最後給出完整解決方案(Nginx為例):
JAVA部分:
Nginx部分:
location ~ ^/static {
proxy_pass ....;
proxy_set_header X-Forward-For $remote_addr ;
}
這就是差距啊~~~