快好知 kuaihz订阅观点

 

小红书一字带,全网的 IP 归属地显示,带你5分钟加上,就是这么简单

最近,继新浪微博之后,今日头条、腾讯、抖音、知乎、快手、小红书、百家号等各大平台陆陆续续都上线了"网络用户IP地址显示功能",境外用户显示的是国家,国内的用户显示的省份,而且此项显示无法关闭,归属地强制显示;

作为技术人,那!这个功能要怎么实现呢?

其实要想实现这个功能还是非常的容易,基于现成 GeoLite2离线库+免费的在线解析资源,5分钟就能整合了;

在整合之前,我们先简单了解一下,要想拿到用户的位置信息,有那些方式:

终端定位

我们的手机等电子设备都是带有GPS定位功能的,APP可以申请权限获取用户所处的经纬度坐标,根据坐标,就可以知道到用户所处的位置;比如百度、高德等地图厂商,就提供了完善的SDK,能非常方便的集成到应用,快速根据经纬度获取详细的位置详细;

优点

快捷;

准确;

误差小。

缺点

依赖硬件支持;

依赖用户授权,如果用户不授权,APP将拿不到经纬度信息,导致失败;

IP地址解析

用户向服务端发起的请求都会带上IP地址,服务端拿到IP地址后,就能基于IP解析出用户的所处的位置;

优点

无需授权,只要用户跟服务端交互,服务端就能拿到对应的IP信息

缺点

准确性不高,位置可能存在偏差;

IP库更新不及时,导致部分IP归属地解析失败。

三方终端上报

比如,我们骑共享单车的时候,我们的位置信息就是通过单车的设备上报到服务器;

优点

由三方终端基于GPS定位上报,不会获取个人设备的信息;

准确快捷;

专业设备,误差小;

缺点

用户无法干预,信息会被迫强制上传至服务端,用户无法取消上传;

下面就来试着将 GeoLite2 免费 IP 库整合值SpringBoot项目,来获取用户的归属地信息;

1什么是GeoLite2?

GeoLite2数据库是免费的IP地理定位数据库;

优点:

离线库,不需要网络

数据库丰富

速度快

免费

缺点:

准确度不高,存在偏差

数据更新慢

2下载 GeoLite2 离线库

官网地址:https://www.maxmind.com/en/home

下载过程稍微有点点麻烦,这里下载了一份最新的,放在网盘,需要测试的可以直接通过这个链接下载:https://www.123pan.com/s/xPY9-J37vH

3SpringBoot 获取用户的IP

工具类public class IpUtils {

/**

* 获取用户IP

* @param request

* @return

*/

public static String getIpAddr(HttpServletRequest request) {

String ip = request.getHeader("x-forwarded-for");

if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {

ip = request.getHeader("X-Real-IP");

}

if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {

ip = request.getHeader("http_client_ip");

}

if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {

ip = request.getRemoteAddr();

}

if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {

ip = request.getHeader("Proxy-Client-IP");

}

if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {

ip = request.getHeader("WL-Proxy-Client-IP");

}

if (ip == null || ip.length() == 0 || "unknown".equalsIgnoreCase(ip)) {

ip = request.getHeader("HTTP_X_FORWARDED_FOR");

}

// 如果是多级代理,那么取第一个ip为客户ip

if (ip != null && ip.indexOf(",") != -1) {

ip = ip.substring(ip.lastIndexOf(",") + 1).trim();

}

return ip;

}

}

Controller获取HttpServletRequest通过上面的工具类,即可获取用户请求的真实IP;为了避免重复工作,这里也可以使用AOP解析出用户的IP信息,放到用户的请求对象中@RestController

public class IpController {

@GetMapping("/user/ip")

public String userIp(HttpServletRequest request) {

// 这里就能拿到用户的真实IP

return IpUtils.getIpAddr(request);

}

}

4SpringBoot 整合 GeoLite2

添加依赖

com.maxmind.geoip2

geoip2

2.3.0


com.maxmind.db

maxmind-db

1.0.0


工具类public class GeoIpUtils {

private static DatabaseReader reader;

private static void init() {

try {

// 创建 GeoLite2 数据库 Reader

// 这里可以放在本地磁盘,也可以随项目放在resource目录下

File database = new File("F:webGeoLite2-City.mmdb");

// 读取数据库内容

reader = new DatabaseReader.Builder(database).build();

} catch (Exception ex) {

}

}

public static void getCityByIP(String ip) throws Exception {

if (null == reader) {

init();

}

InetAddress ipAddress = InetAddress.getByName(ip);

// 获取查询结果

CityResponse response = reader.city(ipAddress);

// 获取国家信息

Country country = response.getCountry();

System.out.println("国家信息:" + JSON.toJSONString(country));

// 获取省份

Subdivision subdivision = response.getMostSpecificSubdivision();

System.out.println("省份信息:" + JSON.toJSONString(subdivision));

//城市

City city = response.getCity();

System.out.println("城市信息:" + JSON.toJSONString(city));

// 获取城市

Location location = response.getLocation();

System.out.println("经纬度信息:" + JSON.toJSONString(location));

}

}

测试public static void main(String[] args) throws Exception {

String ip = "183.19.xxx.138";

GeoIpUtils.getCityByIP(ip);

}

输出结果:国家信息:{"geoNameId":1814991,"isoCode":"CN","name":"China","names":{"de":"China","ru":"Китай","pt-BR":"China","ja":"中国","en":"China","fr":"Chine","zh-CN":"中国","es":"China"}}

省份信息:{"geoNameId":1809935,"isoCode":"GD","name":"Guangdong","names":{"en":"Guangdong","fr":"Province de Guangdong","zh-CN":"广东"}}

城市信息:{"geoNameId":1998011,"name":"Yanqianlaocun","names":{"en":"Yanqianlaocun","zh-CN":"岩前老村"}}

经纬度信息:{"accuracyRadius":500,"latitude":23.3255,"longitude":116.5007,"timeZone":"Asia/Shanghai"}

就这么简单,轻轻松松就能拿到用户IP所处的国家、省份、城市、经纬度等详细信息,可以根据自己的业务需要,对这些数据再做进一步的封装。

5GeoLite2的其他用法

上面介绍的时SpringBoot整合GeoLite2,同样在其他的一些场景下,也是可以利用GeoLite2获取归属地信息;

整合至Nignx,获取用户归属地信息Nginx 整合 GeoLite2 来解析用户的归属地信息,在代理层就直接整理好对应的数据;

ELK中整合GeoLite2ELK 日志整理的时候,可以通过GeoLite2 获取用户的IP归属地信息;然后通过Kibana,就能非常直观的展示用户的地域分布情况;ELK搭建,这才是看日志的正确姿势

6在线方案

上面一开始介绍GeoLite2时就列举了其离线库更新收录不及时的问题,可能导致一些IP在离线库中并不存在,查找的时候,就会报AddressNotFoundException的错误,如下示例:

遇到这种请求,我们要怎么办呢?

下面就来介绍几种在线IP归属地获取的方式,当本地离线库无法获取的时候,就可以利用三方的在线库,来补充完善;

在线获取的优点:

IP更新及时

准确度高

缺点

三方依赖性强

需要付费,免费版本一般都有各种限制

本站资源来自互联网,仅供学习,如有侵权,请通知删除,敬请谅解!
搜索建议:小红  小红词条  一字  一字词条  全网  全网词条  归属  归属词条  加上  加上词条  
干货新媒体运营

 SEM和SEO,SEM-账户常见...

搜索引擎营销账户么,问题常投常有,没问题就没咱优化师什么事了(失业了),所以在账户的分析与优化这事上,形成分析及优化思路还是很有必要的。营销漏斗分析优化因素①展...(展开)