通过IP计算分析归属地
在产品中可能存在不同客户端,请求同一个服务端接口的场景。
例如小程序和App或者浏览器中,如果需要对请求的归属地进行分析,前提是需要先获取请求所在的国家或城市,这种定位通常需要主动授权,而用户一般是不愿意提供的,就需要通过请求的IP来进行归属地计算。
IP地址一般分为两种,IPV4和IPV6,相应的计算方式也有差异,以国家维度来参考,每个国家都有对应的网段范围,计算网段中的最小和最大IP地址的对应数值,然后对比请求的IP地址,来判断属于哪个国家的网段范围。
import cn.hutool.core.net.Ipv4Util;
import cn.hutool.core.util.StrUtil;
import java.math.BigInteger;
import java.net.InetAddress;
public class IpCalculate {
public static void main(String[] args) throws Exception {
// IPv4 网段
String ipv4Network = "IPv4 网段";
String[] ipv4Param = StrUtil.splitToArray(ipv4Network, "/");
// IPv4 起始和结束IP
String ipv4StartIp = Ipv4Util.getBeginIpStr(ipv4Param[0],Integer.parseInt(ipv4Param[1]));
String ipv4OverIp = Ipv4Util.getEndIpStr(ipv4Param[0],Integer.parseInt(ipv4Param[1]));
System.out.println(ipv4StartIp);
System.out.println(ipv4OverIp);
// IPv4 起始和结束IP对应的Long值
System.out.println(Ipv4Util.ipv4ToLong(ipv4StartIp));
System.out.println(Ipv4Util.ipv4ToLong(ipv4OverIp));
// IPv6 网段
String ipv6Network = "IPv6 网段";
String[] ipv6Param =ipv6Network.split("/");
int prefixLength = Integer.parseInt(ipv6Param[1]);
// IPv6 起始和结束IP
InetAddress baseAddress = InetAddress.getByName(ipv6Param[0]);
BigInteger baseValue = new BigInteger(1, baseAddress.getAddress());
BigInteger mask = BigInteger.ONE.shiftLeft(128).subtract(BigInteger.ONE)
.shiftRight(128 - prefixLength).shiftLeft(128 - prefixLength);
BigInteger minIp = baseValue.and(mask);
BigInteger maxIp = minIp.add(BigInteger.ONE.shiftLeft(128 - prefixLength).subtract(BigInteger.ONE));
System.out.println(toIPv6String(minIp));
System.out.println(toIPv6String(maxIp));
// IPv6 起始和结束IP对应的Long值
System.out.println(minIp);
System.out.println(maxIp);
}
private static String toIPv6String(BigInteger value) throws Exception {
byte[] bytes = value.toByteArray();
byte[] ipv6Bytes = new byte[16];
int start = bytes.length > 16 ? bytes.length - 16 : 0;
int length = Math.min(bytes.length, 16);
System.arraycopy(bytes, start, ipv6Bytes, 16 - length, length);
return InetAddress.getByAddress(ipv6Bytes).getHostAddress();
}
}
不过网段地址和国家的对应关系需要进行维护,如果归属地分析不需要非常精准,可以直接使用开源的字典库,比如使用比较多的就是GeoIP2组件。
<dependency>
<groupId>com.maxmind.geoip2groupId>
<artifactId>geoip2</artifactId>
</dependency>
通过组件中提供的API加载相应的文件字典,然后传入IP地址进行归属地判断,这里要注意争议和敏感地区的处理,如果出错产品可不止是上热搜的问题了。
import com.maxmind.geoip2.DatabaseReader;
import java.io.File;
import java.net.Inet4Address;
import java.net.Inet6Address;
import java.net.InetAddress;
public class GeoIpTool {
public static void main(String[] args) throws Exception {
// 读取IP库文件
File ipFile = new File("IP文件库");
DatabaseReader reader = new DatabaseReader.Builder(ipFile).build();
// IPV4地址
InetAddress ipV4 = InetAddress.getByName("IPV4");
if (ipV4 instanceof Inet4Address){
System.out.println(reader.country(ipV4));
System.out.println(reader.country(ipV4).getCountry());
// 默认英文名
System.out.println(reader.country(ipV4).getCountry().getName());
// 查询中文名
System.out.println(reader.country(ipV4).getCountry().getNames().get("zh-CN"));
}
// IPV6地址
InetAddress ipV6 = InetAddress.getByName("IPV6");
if (ipV6 instanceof Inet6Address){
System.out.println(reader.country(ipV6));
System.out.println(reader.country(ipV6).getCountry());
// 默认英文名
System.out.println(reader.country(ipV6).getCountry().getName());
// 查询中文名
System.out.println(reader.country(ipV6).getCountry().getNames().get("zh-CN"));
}
}
}
如果需要非常精确的实时归属地分析,可以购买专业的IP网段数据,实时更新到本地的数据库中,作为IP字典使用,获取请求的IP后,直接范围匹配即可。
CREATE TABLE `ip_place` (
`id` bigint(20) NOT NULL AUTO_INCREMENT,
`network` varchar(100) DEFAULT NULL COMMENT '网段区间',
`min_ip` bigint(20) DEFAULT NULL COMMENT '最小IP',
`max_ip` bigint(20) DEFAULT NULL COMMENT '最大IP',
`min_ip_number` bigint(20) DEFAULT NULL COMMENT '最小IP数值',
`max_ip_number` bigint(20) DEFAULT NULL COMMENT '最大IP数值',
`ip_place` varchar(100) DEFAULT NULL COMMENT '归属地',
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COMMENT='IP归属地';
最后需要补充说一句,对于很多标准的数据,尽可能在项目最初就设计好字典枚举或者数据表,避免后续规范时面临数据清洗的问题。
通过IP计算分析归属地的更多相关文章
- TCP、UDP、IP 协议分析
http://rabbit.xttc.edu.cn/rabbit/htm/artical/201091145609.shtml http://bhsc881114.github.io/2015/06 ...
- TCP、UDP、IP协议分析
此篇文章的原创作者是:草根老师博客(程姚根) chengyaogen.blog.chinaunix.net 感谢原作者! 互连网早期的时候,主机间的互连使用的是NCP协议.这种协议本身有很多缺陷,如: ...
- TCP/IP协议分析
一;前言 学习过TCP/IP协议的人多有一种感觉,这东西太抽象了,没有什么数据实例,看完不久就忘了.本文将介绍一种直观的学习方法,利用协议分析工具学习TCP/IP,在学习的过程中能直观的看到数据的具体 ...
- TCP/IP协议分析(推荐)
一;前言 学习过TCP/IP协议的人多有一种感觉,这东西太抽象了,没有什么数据实例,看完不久就忘了.本文将介绍一种直观的学习方法,利用协议分析工具学习TCP/IP,在学习的过程中能直观的看到数据的具体 ...
- [SuProxy]Ngnix+Lua 实现SSH2,LDAP,ORACLE,SQLSERVER等TCP/IP协议分析,劫持,代理,会话及负载
目录 目录 目录 前言 介绍 安装 下载并拷贝 使用LuaRocks安装 运行测试 使用简介 处理器(processor)创建 通道(channel)创建 负载均衡 会话信息和会话管理 Event H ...
- floating IP 原理分析 - 每天5分钟玩转 OpenStack(107)
上一节我们通过 Web UI 创建为 cirros-vm3 分配了浮动 IP,今天将分析其工作原理. 首先查看 router 的 interface 配置: 可以看到,floating IP 已经配置 ...
- Linux内核TCP/IP参数分析与调优
转载于:http://www.itxuexiwang.com/a/liunxjishu/2016/0225/167.html?1456482565 如下图展示的是TCP的三个阶段.1,TCP三次握手. ...
- C# 根据IP查询地址归属地
必备文件:IPLocation.dll.QQWry.Dat 下载地址:http://pan.baidu.com/s/1jG1dlOy (可百度下载) 之前有过将 QQWry.Dat 转为 Access ...
- tcpdump使用和TCP/IP包分析
关于tcpdump如何抓包,本文不再总结,可以查看 tcpdump的官方地址查看http://www.tcpdump.org 本文重点记录两个部分: 第一部分:tcpdump所抓包 ...
- 软考计算机网络原理之IP计算问题汇总
转自 http://www.cnblogs.com/jyh317/archive/2013/04/14/3018650.html 1.IP地址 分类: ①A类IP地址 ②B类IP地址 ③C类IP地址 ...
随机推荐
- Python实战:为Prometheus开发自定义Exporter
Python实战:为Prometheus开发自定义Exporter 在当今的微服务架构和容器化部署环境中,监控系统的重要性不言而喻.Prometheus作为一款开源的系统监控和警报工具,以其强大的功能 ...
- IDEA 编辑java项目跳过测试
一.Idea配置
- 揭秘 Sdcb Chats 如何解析 DeepSeek-R1 思维链
在上一篇文章中,我介绍了 Sdcb Chats 如何集成 DeepSeek-R1 模型,并利用其思维链(Chain of Thought, CoT)功能增强 AI 推理的透明度.DeepSeek-R1 ...
- Git指南-从入门到精通
代码提交和同步命令 流程图如下: 第零步: 工作区与仓库保持一致 第一步: 文件增删改,变为已修改状态 第二步: git add ,变为已暂存状态 $ git status $ git add --a ...
- Git钩子-每次提交信息添加分支名称
Git钩子是一组脚本,这些脚本对应着Git仓库中的特定事件,每一次事件发生时,钩子会被触发.这允许你可以定制化Git的内部行为,在开发周期中的关键点上触发执行定制化的脚本. 钩子脚本文件通常放置于项目 ...
- 超详细,DeepSeep 接入PyCharm实现AI编程!(支持本地部署DeepSeek及官方DeepSeek接入),建议收藏!
在当今数字化时代,AI编程助手已成为提升开发效率的利器.DeepSeek作为一款强大的AI模型,凭借其出色的性能和开源免费的优势,成为许多开发者的首选.今天,就让我们一起探索如何将DeepSeek接入 ...
- 解锁DeepSeek深度应用,天翼云GPU云主机强势破局!
在人工智能重塑世界的当下,一场影响深远的科技变革正在悄然上演,DeepSeek系列模型在诸多领域掀起热潮.企业级AI模型的训练与部署,不仅是技术的角力场,更是决定企业兴衰的生死线.每一次算法的迭代革新 ...
- [BZOJ3159] 决战 题解
个人感觉各方面难度高于<在美妙的数学王国中畅游>,也不知道是不是求导的关系,这题 \(luogu\) 难度评级还更低.不过感觉这题作完对 \(LCT\) 理解更顺畅了. 前四个操作简单,关 ...
- Jenkins - [02] 安装部署
题记部分 一.Jenkins是什么 Jenkins,原名Hudson,2011年改为现在的名字,它是一个开源的实现持续集成的软件工具. 官网:https://www.jenkins.io/ 官网: ...
- @autowired注解报错原因及解决办法
@autowired 注入dao层的时候,标红报错,但不影响编译使用 按照严格的spring注解方式在dao层加入@Repository注解