本文主要讲解IP查询属地信息的实现方法,以及基于Spring Boot实现IP属地信息查询项目。

〇、前言

近日,多个网络公众平台纷纷公开显示用户的IP属地,并且用户无法开启或关闭此功能。

用户的IP信息,平台是怎么知道的?

其大致流程是这样的:

  • 用户的手机、电脑等设备必须通过网络运营商(电信、移动等)进行联网服务,这个连接网络的过程中,基站、路由器将为该设备动态分配一个IP
  • 用户发布一篇文章或微博,或者进行评论时,就会向平台服务器发送一个HTTP请求。而IP信息,就包含在这个HTTP请求头里;
  • 平台服务器接收到请求信息,就可以通过HTTP请求(Request请求)信息解析出该用户的IP

在这个过程中,请求信息只包含IP,并不包含用户的属地信息

另外,对于交互式平台来说,《互联网交互式服务安全管理要求》(GA 1277.1-2020)的第1部分 基本要求第8.3条 日志与用户数据记录明确,平台必须记录用户的活动、信息发布等操作的IP地址及源端口。详见:http://www.beian.gov.cn/portal/downloadcenter 。

平台如何通过IP查询到属地信息?

一种方案是请求第三方IP属地信息服务的API,通过该接口查询用户的IP属地信息。但这种方案通常是按量付费的,大的平台请求量巨大,不划算。

另外一种方案是使用离线的IP地址数据库,该数据库通常是一个文件,甚至可能是cvs文件、txt文件。

该数据库一般是由专业人士通过专业技术人工生成,其中记录了大量的IP地址(段),并记录了该IP地址(段)所属的国家省份城市运营商名称邮政编码经纬度等信息。

接下来,将基于JavaMaxMindIP地址数据库,讲解如何实现通过IP获取属地信息

一、下载IP地址库

提供离线IP地址数据库的平台有很多,比如:

  • http://www.ipip.net
  • https://user.ip138.com/ip/lib/

这些平台通常是付费的,价格不菲。不过也有平台提供免费版,比如:

  • https://www.maxmind.com/en/geoip2-services-and-databases

MaxMind平台提供的IP地址数据库免费付费两种版本。

虽然免费版更新比较慢,但对于精确度不高的项目来说,够用。

MaxMind免费版IP地址数据库叫做GeoLite2,其下载方式如下。

1、注册并登录账号

访问如下地址,注册平台账号;

  • https://www.maxmind.com/en/geolite2/signup

访问如下地址,登录账号;

  • https://www.maxmind.com/en/account/login

登录成功后进入如下页面:

2、下载IP地址数据库

访问左侧的Download Files按钮,进入IP地址数据库下载页面,如下图所示:

我们选择精确到City的免费版mmdb格式的IP地址数据库文件,并下载。

下载完成后是一个压缩包,打开即可看到mmdb格式的数据库文件。

mmdbMaxMind Database,是MaxMind设计的一种用于存储IP地址数据信息的数据库,其采用二分查找树来加速IP信息的查询。

二、IP地址数据库的简单使用

根据MaxMind的开发文档,该数据库的使用方法很简单,一共分两步:

1、导入依赖包

<dependency><groupId>com.maxmind.geoip2</groupId><artifactId>geoip2</artifactId><version>2.16.1</version>
</dependency>

2、配置并查询

File database = new File("/path/to/maxmind-database.mmdb")// This reader object should be reused across lookups as creation of it is expensive.
// 译:这个reader对象应该在整个查找中重用,因为创建它的成本很高。
DatabaseReader reader = new DatabaseReader.Builder(database).build();// If you want to use caching at the cost of a small (~2MB) memory overhead:
// 译:如果要以较小的内存开销(约2MB)为代价使用缓存,请执行以下操作:
// new DatabaseReader.Builder(file).withCache(new CHMCache()).build();InetAddress ipAddress = InetAddress.getByName("128.101.101.101");CityResponse response = reader.city(ipAddress);Country country = response.getCountry();
System.out.println(country.getIsoCode());

详情:https://dev.maxmind.com/geoip/geolocate-an-ip/databases

三、Spring Boot中使用IP地址库

以下代码只展示关键部分。完整代码详见后文。

1、创建Spring Boot项目

创建完成的Spring Boot项目目录结构,如下图所示。

其中,将下载的IP地址数据库文件,放在resources文件夹中的mmdb目录下。

2、导入依赖

pom.xml文件中,导入如下依赖。

<!-- GeoIp2的依赖 -->
<dependency><groupId>com.maxmind.geoip2</groupId><artifactId>geoip2</artifactId><version>2.16.1</version>
</dependency>

3、创建IP属地信息实体

entity包下,新建一个名为Ip2CityEntity的实体,用来保存查询后的IP属地信息

代码如下,逻辑见注释。

package com.zxdmy.tool.entity;import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.experimental.Accessors;import java.io.Serializable;/*** IP属地信息实体类** @author 拾年之璐* @since 2022/5/1 13:24*/
@Data
@Accessors(chain = true)
@EqualsAndHashCode(callSuper = false)
public class Ip2CityEntity implements Serializable {private static final long serialVersionUID = 1L;/*** IP地址*/private String ip;/*** 国家名称*/private String country;/*** 省份名称*/private String province;/*** 城市名称*/private String city;/*** 经度*/private Double longitude;/*** 维度*/private Double latitude;/*** 查询耗时*/private String cost;
}

4、创建并实现查询工具类

utils包中,新建名为GeoIPUtils的工具类,实现通过IP查询属地信息功能方法。

详细代码如下所示,具体逻辑见注释。

package com.zxdmy.tool.utils;import com.maxmind.db.CHMCache;
import com.maxmind.geoip2.DatabaseReader;
import com.maxmind.geoip2.model.CityResponse;
import com.maxmind.geoip2.record.*;
import com.zxdmy.tool.entity.Ip2CityEntity;import java.io.IOException;
import java.io.InputStream;
import java.net.InetAddress;/*** GeoIP数据库操作工具类** @author 拾年之璐* @since 2022/5/1 12:53*/
public class GeoIPUtils {/*** 数据库文件所在的路径(resources文件内)*/private static final String mmdbPath = "mmdb/GeoLite2-City.mmdb";/*** 设置返回的语言:简体中文*/private static final String CHS = "zh-CN";/*** 读取resources文件中的静态数据库*/private static final InputStream mmdbStream = GeoIPUtils.class.getClassLoader().getResourceAsStream(mmdbPath);/*** 数据库加载器,全局静态,只加载一次*/private static DatabaseReader databaseReader;// 静态代码块,初始化时执行一次static {try {databaseReader = new DatabaseReader.Builder(mmdbStream).withCache(new CHMCache()).build();} catch (IOException e) {e.printStackTrace();}}/*** 通过IP查询地址信息** @param ip IP地址* @return 城市地址信息*/public static Ip2CityEntity getIpInfo(String ip) {Ip2CityEntity ip2CityEntity = new Ip2CityEntity();try {// 获取主机的IP(IP可以是域名)InetAddress inetAddress = InetAddress.getByName(ip);// 通过数据库查询该IP的信息CityResponse response = databaseReader.city(inetAddress);// 解析国家String countryName = response.getCountry().getNames().get(CHS);// 解析二级分支(一般是省份)String provinceName = response.getMostSpecificSubdivision().getNames().get(CHS);// 解析城市String cityName = response.getCity().getNames().get(CHS);// 解析坐标Location location = response.getLocation();// 写入实体ip2CityEntity.setIp(ip).setCountry(countryName).setProvince(provinceName).setCity(cityName)// 经度.setLatitude(location.getLatitude())// 维度.setLongitude(location.getLongitude());} catch (Exception e) {System.out.println(e.getMessage());return null;}return ip2CityEntity;}}

5、调用工具类实现具体业务

接下来就可以在控制类服务类切面等场景中,根据实际业务需求,调用GeoIPUtils工具类中的通过IP查询属地信息静态方法,获取某个IP的属地信息。

下面是一种使用实例。

package com.zxdmy.tool.controller;import com.zxdmy.tool.entity.Ip2CityEntity;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;import static com.zxdmy.tool.utils.GeoIPUtils.getIpInfo;/*** 请求查询的控制器** @author 拾年之璐* @since 2022/5/1 17:19*/
@Controller
public class IPController {/*** 请求的入口** @param ip IP地址* @return 查询结果*/@GetMapping({"query"})@ResponseBodypublic Ip2CityEntity index(@RequestParam(name = "ip", required = false) String ip) {// 请求的开始时间long start = System.currentTimeMillis();// 查询结果Ip2CityEntity ip2CityEntity = getIpInfo(ip);// 判断查询结果if (null != ip2CityEntity) {// 写入查询耗时ip2CityEntity.setCost(System.currentTimeMillis() - start + " ms");}// 返回return ip2CityEntity;}
}

四、结果演示与源码下载

在作者的演示项目中,控制类的实现方法如下图所示,查询返回的是JSON数据

4.1 线上演示

注:线上演示项目不提供长久服务,随时下线。若无法访问,请使用本地演示

直接访问演示项目的主页将查询访问者的IP属地信息

主页连接(点击可访问):

  • http://ip.tool.zxdmy.com

访问结果如下图所示。

如果通过Get方式传入IP参数,则将查询该IP的属地信息

访问格式如下:

  • http://ip.tool.zxdmy.com/?ip=114.44.227.87

访问结果如下图所示。

4.2 本地演示

本地演示前,请先保证本机有JDK 1.8环境。

访问如下链接,即可下载演示项目的jar包

https://download.csdn.net/download/cxh_1231/85259992

使用如下命令运行jar包即可启动项目

java -jar Ip2CityDemo-1.1.jar

详情如下图所示。

关闭该CMD命令行窗口,即结束项目。

4.3 源码下载

请访问如下链接下载。

https://download.csdn.net/download/cxh_1231/85259992

— End —

IP属地信息哪里来的?手把手教你实现通过IP查询属地信息相关推荐

  1. 手把手教你实现显示IP归属地

    手把手教你实现显示IP归属地 实现原理 获取IP地址 调用IP归属地接口: 近年来,根据<国家互联网用户账号名称信息管理规定>要求互联网用户账号服务平台标注IP地址属地信息,微信公众号.抖 ...

  2. mysql sql注入怎么获取数据_手把手教你通过SQL注入盗取数据库信息

    目录数据库结构 注入示例判断共有多少字段 判断字段的显示位置 显示登录用户和数据库名 获取所有数据库名 获取对应数据库的表 获取对应表的字段 获取所有的用户密码 我们都是善良的银!一生戎码只为行侠仗义 ...

  3. NAS如何外网访问?手把手教你申请公网IP(收藏)

    上次的那篇NAS的文章有着很不错的热度,首先是感谢观众老爷们的大力支持啦,那么这篇文章主要是回答一些评论中的问题,而且也为那些第一次接触NAS的小伙伴提供一个简单的参考,如果对这方面想有所了解的,请耐 ...

  4. 用计算机配置打印机IP,网络打印机怎么设置ip(手把手教你设置打印机IP地址)...

    如何设置打印机IP地址,是一个长期以来困好多小伙伴的一个问题,那今天我们就以 HP Laserjet Pro 100 MFP M128系列打印机为例,为大家介绍一下打印机IP地址的设置方法~ 步骤一: ...

  5. python字典输入学生信息_用Python创建一个学生字典并可以查询其中信息

    展开全部 你可以试试这个---------------------------------------------------------- # -*- coding:UTF-8 -*- studen ...

  6. java学生签到系统视频教程_手把手教你做一个Java web学生信息、选课、签到考勤、成绩管理系统附带完整源码及视频开发教程...

    四个阶段的Java web学生信息系统视频教程终于录制完成了,系统用到的知识点有:jsp+servlet+mysql+jquery+ajax,前端采用的是当下最流行的easyui管理框架,全部采用面向 ...

  7. 手把手教你利用Java获取图片GPS信息

    你知道的越多,不知道的就越多,业余的像一棵小草! 成功路上并不拥挤,因为坚持的人不多. 编辑:业余草 推荐:https://www.xttblog.com/?p=5251 一张图片能包含很多敏感信息, ...

  8. 【Python实战】爬虫教程千千万,一到实战全完蛋?今天手把手教你一键采集某网站图书信息数据啦~排名第一的竟是...(爬虫+数据可视化)

    前言 ​一本本书,是一扇扇窗,为追求知识的人打开认知世界的窗口 一本本书,是一双双翅膀,让追求理想的人张开翅膀翱翔 所有文章完整的素材+源码都在

  9. 手把手教你JavaEE的分页查询、分页展示,有了这个,你的项目又多了一个谈资

    前言: 我们在写项目的时候,往往有一些项目的信息展示.而展示的数据量往往是很大的,这时候,加入一个分页的功能往往是最理想的选择. 先简单描述一下功能: 根据你的数据量和指定的页面展示数据条数,进行查询 ...

  10. 隐藏表白技能,python教你如何使用图片exif信息隐藏表白,教你如何修改,查询exif信息。

    " 隐藏表白技能" 你有想过一张图片所包含的信息吗?你有想过一张图片可以为你隐藏表达一些内容吗?你有想过图片的隐藏信息可以为你表达你想要说明的东西吗?以及你可以 用图片去表达你的爱 ...

最新文章

  1. atitit. java jsoup html table的读取解析 总结
  2. Android中Sharedpreferences牵涉到跨进程时不能实时读取的问题
  3. html股票数据代码,股票数据的网站抓取(4.2)代码优化
  4. Spring Boot EasyPoi导出Excel下载
  5. Google比Baidu快(发一个无聊的帖)
  6. 小鹏汽车北京车展发布免费加电、电池租赁计划以及低空飞行汽车
  7. Git GUI,Git Bash,Git CMD标签之间的区别
  8. EC600S-CN CAT1通信模组,2G退网升级4G如何选择,QuecPython开发资源下载
  9. java踩坑记-getResourceAsStream
  10. 修复被破坏了的linux文件系统分区表,修复被破坏了的linux文件系统分区表
  11. MarkDown在VSCode环境下使用
  12. swper 实现滑动切换功能的两种方式
  13. 关于O(log2n)的个人理解
  14. 数字信号处理(3)- z变换
  15. 客户满意度测评模型-层次分析法模型」
  16. 基于FPGA的数字秒表设计(含程序)
  17. 软件测试物理机环境基础
  18. Windows10最优设置
  19. 区块链--拜占庭将军问题--区块链
  20. 2021-08-10校网比赛C题

热门文章

  1. windows安装和使用git工具
  2. Camshift算法
  3. 智慧公厕管理系统不断提升公厕管理水平
  4. 机器学习实战(十一)FP-growth算法
  5. VM在使用过程中开机频繁黑屏(VM14版本问题导致的,频繁开机黑屏)
  6. Vs2010 Qt插件安装教程
  7. opengl编程指南第9版源码编译注意事项
  8. c语言在线电子词典的实验报告,《第十六周实验报告任务3——电子词典》
  9. NAT,代理服务器技术
  10. Android Gallery 3D 特效精华