欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Java之獲取客戶端真實(shí)IP地址的實(shí)現(xiàn)

 更新時(shí)間:2023年12月11日 09:00:22   作者:王廷云的博客  
在開發(fā)工作中,我們常常需要獲取客戶端的IP,本文主要介紹了Jav之獲取客戶端真實(shí)IP地址的實(shí)現(xiàn),具有一定的參考價(jià)值,感興趣的可以了解一下

一、應(yīng)用場景

  • 在投票系統(tǒng)開發(fā)中,為了防止刷票,我們需要限制每個(gè) IP 地址只能投票一次;
  • 當(dāng)網(wǎng)站受到諸如 DDoS(Distributed Denial of Service,分布式拒絕服務(wù)攻擊)等攻擊時(shí),我們需要快速定位攻擊者 IP;
  • 在滲透測(cè)試過程中,經(jīng)常會(huì)碰到網(wǎng)站有 CDN(Content Distribution Network,內(nèi)容交付網(wǎng)絡(luò)),這時(shí)我們需要繞過 CDN 查找真實(shí) IP;

二、獲取客戶端的 IP 地址

服務(wù)端獲取客戶端請(qǐng)求IP地址,常見的包括:remote_addr、x-forwarded-for、client-ip 等請(qǐng)求頭參數(shù):

  • remote_addr:指的是當(dāng)前直接請(qǐng)求的客戶端IP地址,它存在于tcp請(qǐng)求體中,是http協(xié)議傳輸?shù)臅r(shí)候自動(dòng)添加,不受請(qǐng)求頭header的控制。因此,當(dāng)客戶端與服務(wù)器之間不存在任何代理的時(shí)候,通過remote_addr獲取客戶端IP地址是最準(zhǔn)確,也是最安全。remote_addr無法偽造
  • x-forwarded-for,即XFF,是很多代理服務(wù)器在請(qǐng)求轉(zhuǎn)發(fā)時(shí)添加上去的。如果客戶端和服務(wù)器之間存在代理服務(wù)器,那么通過remote_addr獲取的IP就是代理服務(wù)器的地址,并不是客戶端真實(shí)的IP地址。因此,需要代理服務(wù)器(通常是反向代理服務(wù)器)將真實(shí)客戶端的IP地址轉(zhuǎn)發(fā)給服務(wù)器,轉(zhuǎn)發(fā)時(shí)客戶端的真實(shí)IP地址通常就存在于XFF請(qǐng)求頭中。
  • client-ip:同XFF,也是代理服務(wù)器添加的用于轉(zhuǎn)發(fā)客戶端請(qǐng)求的真實(shí)IP地址,同樣保存與請(qǐng)求頭中。

在 Java 中,獲取客戶端 IP 最直接的方式就是使用 request.getRemoteAddr()。這種方式在中間沒有代理的情況下,獲取連接到服務(wù)器的客戶端 IP 的最簡單有效的方式。

但是目前互聯(lián)網(wǎng) Web 應(yīng)用很少會(huì)將應(yīng)用服務(wù)器直接對(duì)外提供服務(wù),一般都會(huì)有一層 Nginx 做反向代理和負(fù)載均衡,有的甚至可能有多層代理。所以,在有反向代理的情況下,直接使用 request.getRemoteAddr() 獲取到的IP地址是Nginx所在服務(wù)器的IP地址,而不是客戶端的 IP。

為了解決上面的問題,很多 HTTP 代理會(huì)在 HTTP 協(xié)議頭中添加 X-Forwarded-For 頭,用來追蹤請(qǐng)求的來源,X-Forwarded-For 的格式如下:

X-Forwarded-For: client1, proxy1, proxy2

X-Forwarded-For 包含多個(gè) IP 地址,每個(gè)值通過逗號(hào)+空格分開,最左邊(client1)是最原始客戶端的IP地址,中間如果有多層代理,每一層代理會(huì)將連接它的客戶端IP追加在 X-Forwarded-For 右邊。

下面就是一種常用的獲取客戶端真實(shí)IP的方法:

public static String getRealIP(HttpServletRequest request) {
    String ip = request.getHeader("X-Forwarded-For");
    if (ip != null) {
    	ip = ip.contains(",") ? ip.split(",")[0] : ip;
    } else {
	    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;
}

注意,要讓 Nginx 支持 X-Forwarded-For 頭,需要配置:

proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

$proxy_add_x_forwarded_for 會(huì)將和 Nginx 直接連接的客戶端 IP 追加在請(qǐng)求原有 X-Forwarded-Fo r值的右邊。

三、IP 偽造及解決方案

1、客戶端可以偽造 X-Forwarded-For

一般的客戶端(例如瀏覽器)發(fā)送HTTP請(qǐng)求是沒有 X-Forwarded-For 頭的,當(dāng)請(qǐng)求到達(dá)第一個(gè)代理服務(wù)器時(shí),代理服務(wù)器會(huì)加上 X-Forwarded-For 請(qǐng)求頭,并將值設(shè)為客戶端的IP地址(也就是最左邊第一個(gè)值),后面如果還有多個(gè)代理,會(huì)依次將IP追加到 X-Forwarded-For 頭最右邊,最終請(qǐng)求到達(dá)Web應(yīng)用服務(wù)器,應(yīng)用通過獲取 X-Forwarded-For 頭取左邊第一個(gè)IP即為客戶端真實(shí)IP。

但是如果客戶端在發(fā)起請(qǐng)求時(shí),請(qǐng)求頭上帶上一個(gè)偽造的 X-Forwarded-For,由于后續(xù)每層代理只會(huì)追加而不會(huì)覆蓋,那么最終到達(dá)應(yīng)用服務(wù)器時(shí),獲取的左邊第一個(gè)IP地址將會(huì)是客戶端偽造的 IP。

2、解決方案:配置 Nginx 反向代理

在直接對(duì)外的Nginx反向代理服務(wù)器上配置:

proxy_set_header X-Forwarded-For $remote_addr;

如果有多層Nginx代理,內(nèi)層的Nginx配置:

proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

在最外層 Nginx(即直接對(duì)外提供服務(wù)的Nginx)使用 $remote_addrb代替上面的 $proxy_add_x_forwarded_for,可以防止偽造 X-Forwarded-For。$proxy_add_x_forwarded_forb會(huì)在原有 X-Forwarded-For 上追加IP,這就相當(dāng)于給了偽造 X-Forwarded-Fo r的機(jī)會(huì)。而 $remote_addr 是獲取的是直接 TCP 連接的客戶端 IP,這個(gè)是無法偽造的,即使客戶端偽造也會(huì)被覆蓋掉,而不是追加。

需要注意的是:如果有多層代理,只在直接對(duì)外訪問的 Nginx 上配置 X-Forwarded-For 為 $remote_addr,內(nèi)層的 Nginx 還是要配置為 $proxy_add_x_forwarded_for,不然內(nèi)層的 Nginx 又會(huì)覆蓋掉客戶端的真實(shí)IP。

完成以上配置后,獲取X-Forwarded-For最左邊的IP地址即為真實(shí)的客戶端地址,且客戶端也無法偽造。

到此這篇關(guān)于Java之獲取客戶端真實(shí)IP地址的實(shí)現(xiàn)的文章就介紹到這了,更多相關(guān)Java獲取客戶端真實(shí)IP地址內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Java遞歸簡單實(shí)現(xiàn)n的階乘

    Java遞歸簡單實(shí)現(xiàn)n的階乘

    這篇文章主要介紹了Java遞歸簡單實(shí)現(xiàn)n的階乘,遞歸(recursion)就是子程序(或函數(shù))直接調(diào)用自己或通過一系列調(diào)用語句間接調(diào)用自己,是一種描述問題和解決問題的基本方法,下面我們舉一個(gè)小小的例子詳情了解一下,需要的朋友可以參考下
    2021-12-12
  • 詳解idea文件右鍵創(chuàng)建New沒有Create New Servlet的解決辦法

    詳解idea文件右鍵創(chuàng)建New沒有Create New Servlet的解決辦法

    這篇文章主要介紹了詳解idea文件右鍵創(chuàng)建New沒有Create New Servlet的解決辦法,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2020-12-12
  • java 分布式與集群的區(qū)別和聯(lián)系

    java 分布式與集群的區(qū)別和聯(lián)系

    本文主要介紹了java分布式與集群的區(qū)別和聯(lián)系,具有很好的參考價(jià)值,下面跟著小編一起來看下吧
    2017-02-02
  • mybatis動(dòng)態(tài)sql之新增與更新方式

    mybatis動(dòng)態(tài)sql之新增與更新方式

    這篇文章主要介紹了mybatis動(dòng)態(tài)sql之新增與更新方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教
    2023-07-07
  • java interface的兩個(gè)經(jīng)典用法

    java interface的兩個(gè)經(jīng)典用法

    這篇文章主要為大家詳細(xì)介紹了java interface的兩個(gè)經(jīng)典用法,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2016-09-09
  • java開發(fā)讀取嵌套jar包中的文件

    java開發(fā)讀取嵌套jar包中的文件

    這篇文章主要為大家介紹了java開發(fā)讀取嵌套jar包中的文件方法示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2023-06-06
  • java LRU(Least Recently Used )詳解及實(shí)例代碼

    java LRU(Least Recently Used )詳解及實(shí)例代碼

    這篇文章主要介紹了java LRU(Least Recently Used )詳解及實(shí)例代碼的相關(guān)資料,Java里面實(shí)現(xiàn)LRU緩存通常有兩種選擇,一種是使用LinkedHashMap,一種是自己設(shè)計(jì)數(shù)據(jù)結(jié)構(gòu),使用鏈表+HashMap,需要的朋友可以參考下
    2016-11-11
  • 聊一聊帶智能提示的spring-boot-starter

    聊一聊帶智能提示的spring-boot-starter

    這篇文章主要介紹了帶智能提示的spring-boot-starter的相關(guān)知識(shí),本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友參考下吧
    2020-11-11
  • mybatis的association傳遞參數(shù)問題示例

    mybatis的association傳遞參數(shù)問題示例

    這篇文章主要介紹了mybatis的association傳遞參數(shù)問題,本文通過示例代碼給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下
    2022-12-12
  • java rocketmq--消息的產(chǎn)生(普通消息)

    java rocketmq--消息的產(chǎn)生(普通消息)

    這篇文章主要介紹了java rocketmq--消息的產(chǎn)生(普通消息),文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,,需要的朋友可以參考下
    2019-06-06

最新評(píng)論