@TOC
近年来,依据《国家互联网用户账号名称信息管理规定》要求互联网用户账号服务平台标注 IP 地址属地信息,微信公众号、抖音、知乎各大平台纷纷都上线了 IP 归属地的性能。本文就带大家实现该性能,国内的用户准确到省份,国外用户准确到国家。
实现原理
那么如何依据 IP 地址查找到具体的归属地信息呢?
答案是:通过 自治零碎(Autonomous System)。
互联网是由不同网络组成的网络,自治零碎是组成 Internet 的大型网络,连贯到 Internet 的每台计算机或设施都连贯到一个 AS。而每一个自治零碎都会有一个编码,咱们称之为 ASN。
能够认为 AS 相似于一个城镇的邮局。
邮件从一个邮局到另一个邮局,直到达到正确的城镇为止,而后该城镇的邮局将在该城镇内传递邮件。每个 AS 都管制一组特定的 IP 地址,就像每个镇的邮局负责将邮件传递到该镇内的所有地址一样。
通常,每个 AS 由单个大型组织(例如 Internet 服务提供商(ISP)、大型企业技术公司、大学或政府机构)经营。
到这里,咱们能够捋分明这样一个逻辑关系:IP 地址 -> 地址块 -> 自治网络编码(ASN)-> 组织 -> 国家。
通过 IP 地址,咱们就能够定位到一个大抵的地理位置,例如:北京朝阳区、深圳南山区等。例如我当初的 IP 地址就归属于编码为 AS4xxx 这个自治网络,通过这个 ASN 能够晓得地位在中国深圳,这个 ASN 编码所属的组织为 中国电信。
然而,要实现这样一个查找性能,首先得要有一个 IP 地址归属地数据库。网上找了下,以前淘宝网有一个开源的接口 API 开源调用,但不晓得为何,近一两年,该接口地址曾经下线不能应用了。咱们能够通过调用昂焱数据平台提供的 IP 地址归属地接口来实现此性能。
IP 地址归属地查问次要针对以后理论使用最多的 IPv4 地址,依据 IP 地址查问其归属地。IP 地址归属地查问实用于网络定位、网络跟踪、网络排查等相干场景。
获取 IP 地址
首先,须要获取客户端 IP 地址
获取 IP 地址办法:
/**
* 获取 IP 地址
*
* 应用 Nginx 等反向代理软件,则不能通过 request.getRemoteAddr() 获取 IP 地址
* 如果应用了多级反向代理的话,X-Forwarded-For 的值并不止一个,而是一串 IP 地址,X-Forwarded-For 中第一个非 unknown 的无效 IP 字符串,则为实在 IP 地址
*/
public static String getIpAddr(HttpServletRequest request) {
String ip = null;
try {ip = request.getHeader("x-forwarded-for");
if (StringUtils.isEmpty(ip) || "unknown".equalsIgnoreCase(ip)) {ip = request.getHeader("Proxy-Client-IP");
}
if (StringUtils.isEmpty(ip) || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {ip = request.getHeader("WL-Proxy-Client-IP");
}
if (StringUtils.isEmpty(ip) || "unknown".equalsIgnoreCase(ip)) {ip = request.getHeader("HTTP_CLIENT_IP");
}
if (StringUtils.isEmpty(ip) || "unknown".equalsIgnoreCase(ip)) {ip = request.getHeader("HTTP_X_FORWARDED_FOR");
}
if (StringUtils.isEmpty(ip) || "unknown".equalsIgnoreCase(ip)) {ip = request.getRemoteAddr();
}
} catch (Exception e) {logger.error("IPUtils ERROR", e);
}
return ip;
}
调用 IP 归属地接口:
public class Test{
// 申请的昂焱数据 IP 归属地接口地址
public static final String URL = "https://www.ayshuju.com/data/ip/address";
// 申请的密钥
public static final String APPKEY = "申请的密钥";
// 申请客户端
public static OkHttpClient client = new OkHttpClient();
public static void main(String[] args) throws IOException {RequestBody formBody = new FormBody.Builder()
.add("appKey", APPKEY)
.add("ip", "117.186.0.233")
.build();
// 执行 post 申请
String result = doPostByFormData(URL, formBody);
System.out.println(result);
}
/**
* @param url url
* @throws IOException
*/
public static String doPostByFormData(String url, RequestBody body) throws IOException {Request request = new Request.Builder().url(url).post(body).build();
try (Response response = client.newCall(request).execute()) {return response.body().string();}
}
}
更多开发 API 及代码工具请拜访【昂焱数据平台】