哎,我早就料到你獲取IP地址的姿勢不對啦!

鏈接:https://blog.csdn.net/takeurhand/article/details/52512200

想必大家對這段代碼並不陌生:

<code>public String getIpAddr(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();
}
return ip;
}/<code>

是的,你搜索到的“java獲取真實IP地址”大多都是如此。但是,以上代碼真的對嗎?

那麼我們看一下具體的代碼。如上,判斷ip地址的優先級是

<code>"x-forwarded-for">
"Proxy-Client-IP">
"WL-Proxy-Client-IP">
request.getRemoteAddr()/<code>

其中帶引號的都是從header中獲取的。

等等!我們都知道header中的值是可以更改的。比如:

<code>$.ajax({
type : "GET",
headers : {"X-Forwarded-For":randomIp,"WL-Proxy-Client-IP":randomIp},
contentType : 'application/x-www-form-urlencoded;charset=utf-8',
url : url,
data:params,
dataType : "text",
success : function(data) {
count++;
console.log("時間:【"+new Date()+"】 執行成功:【"+count+"】次:"+data);

if(max>0){
setTimeout(function wait(){
console.log("等待"+(timeWait)+"ms ...");
vote(max,getRandomNum(maxWait,minWait));
},timeWait);
}
}

}/<code>

代碼出自: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地址”殘卷。

而剩下的部分在這裡:

<code>#Nginx 設置
location ~ ^/static {
proxy_pass ....;
proxy_set_header X-Forward-For $remote_addr ;
}/<code>

這段配置是在前端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部分(自外國朋友Bashan):

哎,我早就料到你獲取IP地址的姿勢不對啦!

Nginx部分(自月影無痕):

<code>location  ~  ^/static {
proxy_pass ....;
proxy_set_header X-Forward-For $remote_addr ;
}/<code>

對了,在這裡說一下,我目前是在職Java開發,如果你現在正在學習Java,瞭解Java,渴望成為一名合格的Java開發工程師,在入門學習Java的過程當中缺乏基礎入門的視頻教程,可以關注並私信我:01。獲取。我這裡有最新的Java基礎全套視頻教程。


分享到:


相關文章: