Java實(shí)現(xiàn)通過IP獲取IP歸屬地的方法(離線+在線)
【寫在前面】
編撰這篇文章還得從之前做安全業(yè)務(wù)需求說(shuō)起,我們都知道安全攻擊都是在某臺(tái)客戶機(jī)上執(zhí)行某些惡意操作(sql注入,DoS/DDoS攻擊),致使服務(wù)端響應(yīng)異常崩潰亦或響應(yīng)數(shù)據(jù)被篡改,那么怎么去阻止這些東西呢?
首先我想到的是對(duì)訪問的web端做一個(gè)IP的校驗(yàn)(好比阿里云服務(wù)器的安全組設(shè)置),建立一些白名單,這樣能在很大程度上做到一個(gè)限制,其實(shí)在服務(wù)端也應(yīng)該要開啟防火墻、設(shè)置權(quán)限等。那么我們首先得知道客戶端的IP是多少。接下來(lái)此文重點(diǎn)介紹如何獲取。
1、如何獲取客戶端訪問IP
其實(shí)獲取IP是最簡(jiǎn)單的,因?yàn)橹灰姓?qǐng)求的話,都會(huì)存放在session里面的,只要通過下面這句話就可以拿到你所需要的IP,但是如何知道別人訪問你的服務(wù)器呢,這個(gè)時(shí)候就需要您自己去寫一個(gè)監(jiān)聽事件listen;
獲取IP方式如下代碼即可:
HttpSession session = request.getSession(false); if (session == null) { session = request.getSession(); System.out.println("session:" + session + "創(chuàng)建成功"); session.setAttribute("ip", request.getRemoteAddr()); System.out.println("----訪問的IP是:"+request.getRemoteAddr()+"----"); }
控制臺(tái)輸出:
2、如何通過IP獲取歸屬地(離線+在線)
通過上面的方式拿到了IP地址,那么我想知道是哪些地方的人訪問了我們的系統(tǒng)的話這就需要后臺(tái)去進(jìn)行查詢了,這才是這篇文章的核心:
2.1 離線模式
主要是通過自己本地的離線庫(kù)來(lái)實(shí)現(xiàn)查找的,有個(gè)弊端就是需要不斷的更新。
第一步:下載離線包ip2region.xdb
首先下載一個(gè)離線的IP歸屬映射包ip2region.xdb,沒有的可以去我的百度云盤上下載
下載地址如下:
鏈接:https://pan.baidu.com/s/1l_Gfhl0TVPYXvpK9QSiXyw
提取碼:hdd6
第二步:引入離線包
將我們的離線包放在resources目錄下,如下圖所示:
Maven引入
打開項(xiàng)目中的pom.xml文件,將下面的代碼復(fù)制到里面去(如果有則忽略):
<!-- ip2region --> <dependency> <groupId>org.lionsoul</groupId> <artifactId>ip2region</artifactId> <version>2.6.5</version> </dependency> <dependency> <groupId>org.apache.commons</groupId> <artifactId>commons-lang3</artifactId> <version>3.9</version> </dependency> <dependency> <groupId>javax.servlet</groupId> <artifactId>javax.servlet-api</artifactId> <version>4.0.1</version> <scope>provided</scope> </dependency> <dependency> <groupId>org.apache.httpcomponents</groupId> <artifactId>httpclient</artifactId> <version>4.5</version> </dependency>
開始引入時(shí)候可能會(huì)報(bào)紅,需要你自己去更新一下maven庫(kù)
沒有報(bào)紅表示本地引入成功。
Pom.xml引入靜態(tài)打包(特別關(guān)鍵,不然會(huì)報(bào)錯(cuò))
[Xxx/ip2region.xdb] cannot be opened because it does not exist
<resource> <directory>src/main/resources</directory> <includes> <include>jdbc.properties</include> <include>*.xml</include> <include>ipdb/*.xdb</include> </includes> </resource>
主要是在構(gòu)建的時(shí)候我們java會(huì)變成class文件進(jìn)行編譯,一些靜態(tài)資源需要自己手動(dòng)去加才能打到j(luò)ar包里面去。
第三步:代碼實(shí)現(xiàn)
控制臺(tái)效果如下所示(國(guó)內(nèi)國(guó)外的都有):
核心實(shí)現(xiàn)代碼(記得要引入一些依賴包喲):
String dbPath = "/ipdb/ip2region.xdb"; try { InputStream inputStream = new ClassPathResource(dbPath).getInputStream(); byte[] dbBinStr = FileCopyUtils.copyToByteArray(inputStream); // 創(chuàng)建一個(gè)完全基于內(nèi)存的查詢對(duì)象 searcher = Searcher.newWithBuffer(dbBinStr); } catch (Exception e) { System.out.printf("failed to create content cached searcher: %s\n", e); } //把ip2r String address = ""; try { address = searcher.search("66.249.79.193"); } catch (Exception e) { throw new RuntimeException(e); } System.out.println("=== 訪問者的地址為:"+address+" === ");
到這里我們就只要維護(hù)好那個(gè)離線包文件就可以,定時(shí)更新一下。
2.2 在線模式
主要通過別人或者官網(wǎng)提供的API接口去實(shí)現(xiàn)查詢的功能,有個(gè)弊端就是特別依賴別人的服務(wù)器,萬(wàn)一別人服務(wù)器掛了就訪問不了了。
具體實(shí)現(xiàn)效果和2.1離線模式介紹的一樣
主要實(shí)現(xiàn)我封裝到一個(gè)java類里面,寫了一些特定的方法;
如下所示:
public static String getAddress(String ip) { try { URL realUrl = new URL("http://whois.pconline.com.cn/ipJson.jsp?ip=" + ip + "&json=true"); HttpURLConnection conn = (HttpURLConnection) realUrl.openConnection(); conn.setRequestMethod("GET"); conn.setUseCaches(false); conn.setReadTimeout(6000); conn.setConnectTimeout(6000); conn.setInstanceFollowRedirects(false); int code = conn.getResponseCode(); StringBuilder sb = new StringBuilder(); String ipaddr = ""; if (code == 200) { InputStream in = conn.getInputStream(); BufferedReader reader = new BufferedReader(new InputStreamReader(in)); String line; while ((line = reader.readLine()) != null) { sb.append(line); } ipaddr = ip + "=" + sb.substring(sb.indexOf("addr") + 7, sb.indexOf("regionNames") - 3); } return ipaddr; } catch (Exception e) { e.printStackTrace(); return null; } }
調(diào)用地方如下所示:
String address = IpAddressUtils.getAddress("66.249.79.193"); System.out.println("=== (在線)訪問者的地址為:"+address+" === ");
3、推薦方式,先離線后在線
【重要】其實(shí)我們可以結(jié)合兩個(gè)使用一起,先采用離線,如果發(fā)現(xiàn)為null的話則調(diào)用在線查詢的方式。這樣在一定的程度上能夠保證數(shù)據(jù)的完整性,都有不足的話就互補(bǔ)一下;如下所示邏輯:
System.out.println("--- (在線+離線)訪問者的IP為:66.249.79.193 --- "); //================離線模式獲取=start====================// String dbPath = "/ipdb/ip2region.xdb"; try { InputStream inputStream = new ClassPathResource(dbPath).getInputStream(); byte[] dbBinStr = FileCopyUtils.copyToByteArray(inputStream); // 創(chuàng)建一個(gè)完全基于內(nèi)存的查詢對(duì)象 searcher = Searcher.newWithBuffer(dbBinStr); } catch (Exception e) { System.out.printf("failed to create content cached searcher: %s\n", e); } //把ip2r String address = ""; try { address = searcher.search("221.231.220.212"); } catch (Exception e) { throw new RuntimeException(e); } // String address = IpAddressUtils.getCityInfo("66.249.79.193"); System.out.println("=== (離線)訪問者的地址為:"+address+" === "); //================離線模式獲取=end====================// //======================在線模式獲取 start========================// if("".equals(address)){ address = IpAddressUtils.getAddress("66.249.79.193"); System.out.println("=== (在線)訪問者的地址為:"+address+" === "); } //======================在線模式獲取 end========================//
4、最后
以上就是Java實(shí)現(xiàn)通過IP獲取IP歸屬地的方法(離線+在線)的詳細(xì)內(nèi)容,更多關(guān)于Java獲取IP歸屬地的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
關(guān)于@SpringBootApplication與@SpringBootTest的區(qū)別及用法
這篇文章主要介紹了關(guān)于@SpringBootApplication與@SpringBootTest的區(qū)別及用法,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2022-01-01詳解Java線程池如何統(tǒng)計(jì)線程空閑時(shí)間
這篇文章主要和大家分享一個(gè)面試題:Java線程池是怎么統(tǒng)計(jì)線程空閑時(shí)間?文中的示例代碼講解詳細(xì),對(duì)我們掌握J(rèn)ava有一定幫助,需要的可以參考一下2022-11-11java實(shí)現(xiàn)多文件上傳至本地服務(wù)器功能
這篇文章主要為大家詳細(xì)介紹了java實(shí)現(xiàn)多文件上傳至本地服務(wù)器功能,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2018-01-01Spring工廠方法創(chuàng)建(實(shí)例化)bean實(shí)例代碼
這篇文章主要介紹了Spring工廠方法創(chuàng)建bean實(shí)例代碼,具有一定借鑒價(jià)值,需要的朋友可以參考下2018-01-01Springboot使用Spring Data JPA實(shí)現(xiàn)數(shù)據(jù)庫(kù)操作
Spring Data JPA 是 Spring 基于 Spring Data 框架、在JPA 規(guī)范的基礎(chǔ)上開發(fā)的一個(gè)框架,使用 Spring Data JPA 可以極大地簡(jiǎn)化JPA 的寫法,本章我們將詳細(xì)介紹在Springboot中使用 Spring Data JPA 來(lái)實(shí)現(xiàn)對(duì)數(shù)據(jù)庫(kù)的操作2021-06-06Maven pom的distributionManagement配置方式
文章主要介紹了Maven的distributionManagement配置方式,以及它的作用、配置方法和重要性,distributionManagement用于指定構(gòu)件的發(fā)布位置,包括下載URL、狀態(tài)等,文章還詳細(xì)解釋了如何配置repository和snapshotRepository,以及它們的用途和區(qū)別2025-01-01tk.mybatis實(shí)現(xiàn)uuid主鍵生成的示例代碼
本文主要介紹了tk.mybatis實(shí)現(xiàn)uuid主鍵生成的示例代碼,文中通過示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2021-12-12Java Math.round(),Math.ceil(),Math.floor()的區(qū)別詳解
這篇文章主要介紹了Java Math.round(),Math.ceil(),Math.floor()的區(qū)別詳解,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧2020-08-08