全网都在显示的IP归属地,5分钟带你加上,就这么简单

  |   0 评论   |   0 浏览

image-20220515220102985 如遇图片加载失败,可尝试使用手机流量访问

大家好,我是一航!

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

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

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

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

  • 终端定位

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

    优点

    • 快捷;
    • 准确;
    • 误差小。

    缺点

    • 依赖硬件支持;
    • 依赖用户授权,如果用户不授权,APP将拿不到经纬度信息,导致失败;
  • IP地址获取

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

    优点

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

    缺点

    • 准确性不高,位置可能存在偏差;
    • IP库更新不及时,导致部分IP归属地解析失败。
  • 三方终端上报

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

    优点

    • 由三方终端基于GPS定位上报,不会获取个人设备的信息;
    • 准确快捷;
    • 专业设备,误差小;

    缺点

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

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

什么是GeoLite2?

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

优点:

  • 离线库,不需要网络
  • 数据库丰富
  • 速度快
  • 免费

缺点:

  • 准确度不高,存在偏差
  • 数据更新慢

下载 GeoLite2 离线库

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

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

SpringBoot 获取用户的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 != nul