最近,继新浪微博之后,今日头条、腾讯、抖音、知乎、快手、小红书、百家号等各大平台陆陆续续都上线了"网络用户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

  • 添加依赖<dependency>
    <groupId>com.maxmind.geoip2</groupId>
    <artifactId>geoip2</artifactId>
    <version>2.3.0</version>
    </dependency>
    <dependency>
    <groupId>com.maxmind.db</groupId>
    <artifactId>maxmind-db</artifactId>
    <version>1.0.0</version>
    </dependency>
  • 工具类public class GeoIpUtils {
    private static DatabaseReader reader;
    private static void init() {
    try {
    // 创建 GeoLite2 数据库 Reader
    // 这里可以放在本地磁盘,也可以随项目放在resource目录下
    File database = new File("F:\\web\\GeoLite2-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更新及时
  • 准确度高

缺点

  • 三方依赖性强
  • 需要付费,免费版本一般都有各种限制

以下示例中的xxx.xxx.xxx.xxx均代表ip地址;

百度

地址:https://opendata.baidu.com/api.php?query=xxx.xxx.xxx.xxx&resource_id=6006&co=&oe=utf8

响应数据:

{"status": "0","t": "","set_cache_time": "","data": [{"ExtendedLocation": "","OriginQuery": "183.19.xxx.138","appinfo": "","disp_type": 0,"fetchkey": "183.19.xxx.138","location": "广东省肇庆市 电信","origip": "183.19.xxx.138","origipquery": "183.19.xxx.138","resourceid": "6006","role_id": 0,"shareImage": 1,"showLikeShare": 1,"showlamp": "1","titlecont": "IP地址查询","tplt": "ip"}]
}

status等于0表示成功,1表示失败;可能存在status等于0,但是data中没有数据的情况。

ip-api接口

  • 本机的IP信息http://ip-api.com/json/
  • 指定国际化http://ip-api.com/json/?lang=zh-CN
  • 指定IP查询http://ip-api.com/json/xxx.xxx.xxx.xxx?lang=zh-CN返回数据:{
    "status": "success",
    "country": "中国",
    "countryCode": "CN",
    "region": "GD",
    "regionName": "广东",
    "city": "岩前老村",
    "zip": "",
    "lat": 23.3255,
    "lon": 116.5007,
    "timezone": "Asia/Shanghai",
    "isp": "Chinanet",
    "org": "Chinanet GD",
    "as": "AS4134 CHINANET-BACKBONE",
    "query": "183.19.xxx.138"
    }

搜狐IP查询

地址:http://pv.sohu.com/cityjson?ie=utf-8

返回数据比较的简单:

var returnCitySN = {"cip": "xxx.xxx.xxx.xxx", "cid": "440300", "cname": "广东省深圳市"};

太平洋IP地址查询

地址:http://whois.pconline.com.cn/ipJson.jsp?ip=xxx.xxx.xxx.xxx&json=true

返回数据:

{"ip": "183.17.xxx.138","pro": "广东省","proCode": "440000","city": "深圳市","cityCode": "440300","region": "","regionCode": "0","addr": "广东省深圳市 电信","regionNames": "","err": ""
}

淘宝API接口

http://ip.taobao.com/service/getIpInfo.php?ip=xxx.xxx.xxx.xxx

{"code": 0,"data": {"ip": "183.17.xxx.138","country": "中国","area": "","region": "广东","city": "深圳","county": "XX","isp": "电信"}
}

code等于0表示成功,1表示失败

126

地址:https://ip.ws.126.net/ipquery?ip=xxx.xxx.xxx.xxx

响应数据:

var lo="广东省", lc="肇庆市";
var localAddress={city:"肇庆市", province:"广东省"}

响应的数据比较的简单

IP信息

地址:https://ip.useragentinfo.com/json?ip=xxx.xxx.xxx.xxx

响应数据:

{"country": "中国","short_name": "CN","province": "广东省","city": "肇庆市","area": "德庆县","isp": "电信","net": "","ip": "183.19.xxx.138","code": 200,"desc": "success"
}

这么多的姿势,实现起来是不是就非常的容易了;如果你对IP解析的需求比较依赖,也完全可以通过离线加这么多在线的方式,开发一个单独的IP解析模块,作为公司的基础服务,提供给内部其他模块使用。

示例目录:https://github.com/vehang/ehang-spring-boot/tree/main/spring-boot-004-request-validate/src/main/java/com/ehang/validate/geoip

全网的 IP 归属地显示,带你5分钟加上,就是这么简单相关推荐

  1. 米扑博客:总结分享 WordPress显示评论者IP归属地、浏览器、终端设备、电信运营商...

    在网上查资料闲逛,偶然间看到了张戈博客的评论框有点意思,于是就收走拿到了我的米扑博客. 本文为米扑博客原创:总结分享 WordPress显示评论者IP归属地.浏览器.终端设备.电信运营商 WordPr ...

  2. 米扑博客:总结分享 WordPress显示评论者IP归属地、浏览器、终端设备、电信运营商... 1

    2019独角兽企业重金招聘Python工程师标准>>> 在网上查资料闲逛,偶然间看到了张戈博客的评论框有点意思,于是就收走拿到了我的米扑博客. 本文为米扑博客原创:总结分享 Word ...

  3. WordPress显示评论者IP归属地、浏览器、终端设备、电信运营商

    在网上查资料闲逛,偶然间看到了张戈博客的评论框有点意思,于是就收走拿到了我的米扑博客. 本文为米扑博客原创:总结分享 WordPress显示评论者IP归属地.浏览器.终端设备.电信运营商 WordPr ...

  4. 独家直播双十一全网动态?前黑客“劳改”带你玩转大数据

    独家直播双十一全网动态?前黑客"劳改"带你玩转大数据 发表于2015-11-24 10:26| 4044次阅读| 来源CSDN| 7 条评论| 作者蒲婧 CTO俱乐部CTOCTO讲 ...

  5. 【自制小工具】快速批量查询IP归属地(自动去重、按国内外汇总,并智能识别出错误IP)

    作者:Eason_LYC 不放弃,不为别的,只想活成自己心中的样子~ 领域:WEB安全.网络攻防 关注WEB安全.网络攻防.我的专栏文章知识点全面细致,逻辑清晰.结合实战,让你在学习路上事半功倍,少走 ...

  6. 虚拟机ifconfig或ip addr不显示ip地址

    虚拟机ifconfig或ip addr不显示ip地址 报错图片: 一直查不到ip地址,有重新启动很多次 解决方法 (1) 命令查看配置文件: vi /etc/sysconfig/network-scr ...

  7. IP 归属地查询 API 教你从0到1顺着网线找到键盘侠

    写在前面 前一段时间,微博.头条.抖音.知乎等各大互联网平台相继推出了"个人主页.评论显示 IP 属地,用户不能自己开启或关闭"的功能,那么这些平台是如何获取到用户的 IP 地址呢 ...

  8. 全网进入“IP归属地”模式,键盘侠老实了,这些人也慌了

    最近一段比较火的事情可能就是全网进入"IP归属地"模式这件事了,其中包括某音.某手.某乎等等一系列自媒体平台,官方的每一次动作都会有一些人起飞,同样,也会有一部分人发慌了. 起飞的 ...

  9. ping mac地址_局域网ip地址如何显示?一个软件搞定

    上次弱电行业网提到关于局域网ip地址如何显示的问题,提供了两种方法,都是通过代码实现的,对于有一定网络基础的朋友来说,肯定是比较简单的,但也有朋友反映不怎么好操作,那有没有更简单的方法呢?答案是肯定有 ...

  10. Leaflet中使用awesome-markers插件显示带图标的marker

    场景 Vue+Leaflet实现加载OSM显示地图: Vue+Leaflet实现加载OSM显示地图_BADAO_LIUMANG_QIZHI的博客-CSDN博客 在上面的基础上,实现Marker上带图标 ...

最新文章

  1. WP7下巧用MediaElement在雪藏中
  2. 【数据挖掘】决策树 分类 ( 抽取分类规则 | 过拟合 | 剪枝 | 先剪 | 后剪 | 连续数值离散化 | 最优化分点 | 增益率选择划分属性 )
  3. mysql+零时数据结构,MySql主要索引数据结构
  4. linux常用命令和选项
  5. angularjs 默认跳转
  6. VxWorks系统BSP配置文件及生成下载
  7. Storm程序的并发机制原理总结
  8. 中南大学计算机学院夏令营2021,baihhh
  9. 经典面试题:Integer c=100,d=100,c==d 一定是false吗?
  10. Shell常用快捷键
  11. 转载 Log4j2在WEB项目中配置
  12. 接口测试之Postman使用全图文指南(原来使用Postman测试API接口如此简单)
  13. 爱奇艺技术分享:轻松诙谐,讲解视频编解码技术的过去、现在和将来
  14. 计算机怎样打开鼠标点的键盘,电脑软键盘怎么打?
  15. 生产订单完工确认(CO11N) BAPI : BAPI_PRODORDCONF_CREATE_TT
  16. Ubuntu18.04 配置nvidia 460驱动、cuda10.1和cudnn7.6.5
  17. 微信小程序|飞翔的圣诞老人
  18. 仿新浪抢工长装修招标网站源码
  19. MATLAB柱状图画法(详细)
  20. DevOps运维自动化工具系统平台

热门文章

  1. 双显卡(Intel+Nvidia)笔记本配置cuda开发环境
  2. 计算机启动显示不正确的分区表,双硬盘启动失败提示“无效分区表”无法打开机器...
  3. 超实用的 Python 技巧,异步操作数据库!
  4. flex java blazeds 注解_flex java blazeds 注解
  5. 织梦DedeCMS从入门到精通建站视频教程全集
  6. Android开发实现选择城市界面,可根据拼音、首字母进行搜索
  7. windows批量修改文件权限
  8. 『HDU 5855』Less Time, More profit
  9. html去除背景颜色怎么设置,word背景颜色怎么去掉
  10. Parallel Stream 的错误实践