java?IP歸屬地功能實(shí)現(xiàn)詳解
第一步:如何拿到用戶(hù)的真實(shí)IP
大家都知道,我們一般想訪問(wèn)公網(wǎng),一般必須具備上網(wǎng)環(huán)境,那么我們開(kāi)通寬帶之后,運(yùn)營(yíng)商會(huì)給我們分配一個(gè)IP地址。一般IP地址我們都是自動(dòng)分配的。所以我們不知道本機(jī)地址是什么?想知道自己的ip公網(wǎng)地址,可以通過(guò)百度搜索IP查看自己的ip位置

那么問(wèn)題來(lái)了。百度是怎么知道我的公網(wǎng)IP的?
一般情況,用戶(hù)訪問(wèn)我們的服務(wù)網(wǎng)絡(luò)拓?fù)淙缦拢?/p>

用戶(hù)通過(guò)域名或者IP訪問(wèn)門(mén)戶(hù),然后請(qǐng)求到后端服務(wù)。這樣的話后端服務(wù)就可以通過(guò)request.getRemoteAddr();方法獲取用戶(hù)的ip。
SpringBoot獲取IP如下:
@RestController
public class IpController {
@RequestMapping("/getIp")
public String hello(HttpServletRequest request) {
String ip = request.getRemoteAddr();
System.out.println(ip);
return ip;
}
}
將服務(wù)部署到服務(wù)端,然后請(qǐng)求該接口,即可獲取IP信息,如下圖:

但是為什么我們獲取的IP和百度搜出來(lái)的不一樣呢?
1.1內(nèi)網(wǎng)IP和外網(wǎng)IP
打開(kāi)電腦CMD,輸出ipconfig命令,查看本機(jī)的IP地址,發(fā)現(xiàn)我們本機(jī)地址和程序獲取的地址是一樣的。

其實(shí),網(wǎng)絡(luò)也是分內(nèi)網(wǎng)IP和公網(wǎng)IP的。內(nèi)網(wǎng)也成局域網(wǎng)。對(duì)于像公司,學(xué)校這種一般內(nèi)部建立自己的局域網(wǎng),對(duì)內(nèi)部的信息進(jìn)行傳輸時(shí),都是通過(guò)內(nèi)網(wǎng)相互通訊,建立局域網(wǎng)內(nèi)網(wǎng)通訊節(jié)省了公網(wǎng)IP資源,并且通信效率也有很大的提升。當(dāng)然非局域網(wǎng)內(nèi)的設(shè)備則無(wú)法向內(nèi)網(wǎng)的設(shè)備發(fā)送信息。
但是機(jī)器想要訪問(wèn)互聯(lián)網(wǎng)的資源時(shí),則需要機(jī)器擁有外網(wǎng)帶寬,也就是我們所說(shuō)的分配公網(wǎng)IP,負(fù)責(zé)也是無(wú)法訪問(wèn)互聯(lián)網(wǎng)資源的。

因此,我們把服務(wù)部署在同一局域網(wǎng)內(nèi),客戶(hù)端使用內(nèi)網(wǎng)進(jìn)行通信,因此獲取的就是內(nèi)網(wǎng)IP地址。但訪問(wèn)百度是需要使用公網(wǎng)訪問(wèn),因此百度搜出來(lái)的IP就是公網(wǎng)IP地址。
1.2.為什么有時(shí)候獲取到的客戶(hù)端IP有問(wèn)題?
當(dāng)我們興致勃勃的把IP獲取的功能搞上去之后,發(fā)現(xiàn)獲取的IP都是同一個(gè)?這是為什么呢?不可能只是一個(gè)用戶(hù)在訪問(wèn)呀?查詢(xún)IP信息之后發(fā)現(xiàn),原來(lái)是我們部署的一臺(tái)負(fù)載均衡的IP地址。

那么后端服務(wù)獲取的地址都是負(fù)載均衡如nginx的地址。那么怎么透過(guò)負(fù)載均衡獲取真實(shí)的地址呢?
透明的代理服務(wù)器在將客戶(hù)端的訪問(wèn)請(qǐng)求轉(zhuǎn)發(fā)到下一環(huán)節(jié)的服務(wù)器時(shí),會(huì)在HTTP的請(qǐng)求頭中添加一條X-Forwarded-For記錄,用于記錄客戶(hù)端的IP,格式為X-Forwarded-For:客戶(hù)端IP。如果客戶(hù)端和服務(wù)器之間有多個(gè)代理服務(wù)器,則X-Forwarded-For記錄使用以下格式記錄客戶(hù)端IP和依次經(jīng)過(guò)的代理服務(wù)器IP:X-Forwarded-For:客戶(hù)端IP, 代理服務(wù)器1的IP, 代理服務(wù)器2的IP, 代理服務(wù)器3的IP, ……。
因此,常見(jiàn)的Web應(yīng)用服務(wù)器可以通過(guò)解析X-Forwarded-For記錄獲取客戶(hù)端真實(shí)IP。
public static String getIp(HttpServletRequest request) {
String ip = request.getHeader("x-forwarded-for");
if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {
ip = request.getRemoteAddr();
} else if (ip.length() > 15) {
//多次反向代理后會(huì)有多個(gè)ip值,第一個(gè)ip才是真實(shí)ip
String[] ips = ip.split(",");
for (int index = 0; index < ips.length; index++) {
String strIp = ips[index];
ip = strIp;
break;
}
}
return ip;
}
第二步:如何解析IP
IP來(lái)了,我們?cè)趺唇馕瞿兀?/p>
IP的解析一般都要借助第三方軟件使用了,第三方一般也分為離線庫(kù)和在線庫(kù)
- 離線庫(kù)支持的有如:IPIP,使用離線庫(kù)的好處是解析效率高,性能好,問(wèn)題就是IP庫(kù)要經(jīng)常更新。如果大家需要我私信我可以提供給大家比較新版本的ip庫(kù)。
- 在線庫(kù)則各大云廠商接口能力都有支持。在線版本的好處是更新即時(shí),問(wèn)題就是接口查詢(xún)性能和使用TPS有要求。
以下演示借助IP庫(kù)離線IP解析方式:
借助IP庫(kù)就可以幫我們實(shí)現(xiàn)ip地址的解析。
public static void main(String[] args) {
IpAddrInfo IpAddrInfo = IPAddr.getInstance().putLocInfo("114.103.71.226");
System.out.println(JSONObject.toJSONString(IpAddrInfo));
}
public IpAddrInfo putLocInfo(String ip) {
IpAddrInfo info = new IpAddrInfo();
if (StringUtils.isNotBlank(ip)) {
try {
DistrictInfo addrInfo = db.findInfo(ip, "CN");
info.setCity(addrInfo.getCityName());
info.setCountry(addrInfo.getCountryName());
info.setCountryCode(addrInfo.getChinaAdminCode());
info.setIsp(addrInfo.getIsp());
info.setLat(addrInfo.getLatitude());
info.setLon(addrInfo.getLongitude());
info.setProvince(addrInfo.getRegionName());
info.setTimeZone(addrInfo.getTimeZone());
System.out.println(addrInfo.toString());
} catch (IPFormatException e) {
e.printStackTrace();
} catch (InvalidDatabaseException e) {
e.printStackTrace();
}
}
return info;
}

其實(shí)IP的定位解析其實(shí)就是一個(gè)巨大的位置庫(kù),同時(shí)IP數(shù)量也是有限制的,因此同一個(gè)Ip也可能會(huì)分配到不同的區(qū)域,因此影響IP解析位置準(zhǔn)確率的有幾個(gè)方面
1、位置庫(kù)不精準(zhǔn),導(dǎo)致解析偏差大或者地區(qū)字段確實(shí)
2、離線庫(kù)更新不及時(shí) 并且海外的一般有專(zhuān)門(mén)的離線庫(kù)去支持,使用同一套離線庫(kù)并不一定支持海外IP的解析,所以本次受影響最大的海外網(wǎng)紅門(mén)被解析到中國(guó)各個(gè)地區(qū),被大家認(rèn)為造假,當(dāng)然也包括真的有造假。
不過(guò)上線了這個(gè)功能也是有好處的,至少網(wǎng)絡(luò)不是法外之地,大家也要有序的健康的沖浪,拒絕網(wǎng)絡(luò)暴力。
以上就是java IP歸屬地功能實(shí)現(xiàn)詳解的詳細(xì)內(nèi)容,更多關(guān)于java IP歸屬地的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
Java判斷List中相同值元素的個(gè)數(shù)實(shí)例
今天小編就為大家分享一篇Java判斷List中相同值元素的個(gè)數(shù)實(shí)例,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。一起跟隨小編過(guò)來(lái)看看吧2018-07-07
避免多個(gè)jar通過(guò)maven打包導(dǎo)致同名配置文件覆蓋沖突問(wèn)題
這篇文章主要介紹了避免多個(gè)jar通過(guò)maven打包導(dǎo)致同名配置文件覆蓋沖突問(wèn)題,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2023-05-05
Java的編譯時(shí)錯(cuò)誤和運(yùn)行時(shí)錯(cuò)誤問(wèn)題
這篇文章主要介紹了Java的編譯時(shí)錯(cuò)誤和運(yùn)行時(shí)錯(cuò)誤問(wèn)題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-04-04
Springboot整合freemarker 404問(wèn)題解決方案
這篇文章主要介紹了Springboot整合freemarker 404問(wèn)題解決方案,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-05-05
Spring security用戶(hù)URL權(quán)限FilterSecurityInterceptor使用解析
這篇文章主要介紹了Spring security用戶(hù)URL權(quán)限FilterSecurityInterceptor使用解析,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2019-12-12
MyBatis的@SelectProvider注解構(gòu)建動(dòng)態(tài)SQL方式
這篇文章主要介紹了MyBatis的@SelectProvider注解構(gòu)建動(dòng)態(tài)SQL方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2024-08-08

