1987WEB视界-分享互联网热门产品和行业

您现在的位置是:首页 > 短视频 > 正文

短视频

你知道抖音的IP归属地是怎么实现的吗

1987web2023-10-20短视频97
1.背景最近刷抖音发现上线了IP属地的功能,小伙伴在发表动态、发表评论以及聊天的时候,都会显示自己的

1.背景

最近刷抖音发现上线了IP属地的功能,小伙伴在发表动态、发表评论以及聊天的时候,都会显示自己的IP属地信息,其核心意义是让用户更具有真实性,减少虚假欺骗事件。正好最近本人开发获取客户端ip,做一些接口限流,黑白名单等需求功能,顺路就研究了一下怎么解析IP获取归属地问题。

接下来,就着重讲解一下Java后端怎么实现IP归属地的功能,其实只需要以下两大步骤:

2.获取客户端ip接口

做过web开发都知道,无论移动端还是pc端的请求接口都会被封装成为一个HttpServletRequest对象,该对象包含了客户端请求信息包括请求的地址,请求的参数,提交的数据等等。

如果服务器直接把IP暴露出去,那么request.getRemoteAddr()就能拿到客户端ip。

但目前流行的架构中,基本上服务器都不会直接把自己的ip暴露出去,一般前面还有一层或多层反向代理,常见的nginx居多。 加了代理后,相当于服务器和客户端中间还有一层,这时·request.getRemoteAddr()拿到的就是代理服务器的ip了,并不是客户端的ip。所以这种情况下,一般会在转发头上加X-Forwarded-For等信息,用来跟踪原始客户端的ip。

X-Forwarded-For: 这是一个 Squid 开发的字段,只有在通过了HTTP代理或者负载均衡服务器时才会添加该项。 格式为X-Forwarded-For:client1,proxy1,proxy2,一般情况下,第一个ip为客户端真实ip,后面的为经过的代理服务器ip。 上面的代码注释也说的很清楚,直接截取拿到第一个ip。Proxy-Client-IP/WL- Proxy-Client-IP: 这个一般是经过apache http服务器的请求才会有,用apache http做代理时一般会加上Proxy-Client-IP请求头,而WL-Proxy-Client-IP是他的weblogic插件加上的头。这种情况也是直接能拿到。HTTP_CLIENT_IP: 有些代理服务器也会加上此请求头。X-Real-IP:nginx一般用这个。

但是在日常开发中,并没有规范规定用以上哪一个头信息去跟踪客户端,所以都有可能,只能一一尝试,直到获取到为止。代码如下:

@Slf4jpublicclassIpUtils{privatestaticfinalString UNKNOWN_VALUE ="unknown";privatestaticfinalString LOCALHOST_V4 ="127.0.0.1";privatestaticfinalString LOCALHOST_V6 ="0:0:0:0:0:0:0:1"; ​privatestaticfinalString X_FORWARDED_FOR ="X-Forwarded-For";privatestaticfinalString X_REAL_IP ="X-Real-IP";privatestaticfinalString PROXY_CLIENT_IP ="Proxy-Client-IP";privatestaticfinalString WL_PROXY_CLIENT_IP ="WL-Proxy-Client-IP";privatestaticfinalString HTTP_CLIENT_IP ="HTTP_CLIENT_IP"; ​privatestaticfinalString IP_DATA_PATH ="/Users/shepherdmy/Desktop/ip2region.xdb";privatestaticbyte[] contentBuff;/**     * 获取客户端ip地址     *@paramrequest     *@return*/publicstaticStringgetRemoteHost(HttpServletRequest request){        String ip = request.getHeader(X_FORWARDED_FOR);if(StringUtils.isNotEmpty(ip) && !UNKNOWN_VALUE.equalsIgnoreCase(ip)) {// 多次反向代理后会有多个ip值,第一个ip才是真实ipintindex = ip.indexOf(",");if(index != -1) {returnip.substring(0, index);           }else{returnip;           }       }        ip = request.getHeader(X_REAL_IP);if(StringUtils.isNotEmpty(ip) && !UNKNOWN_VALUE.equalsIgnoreCase(ip)) {returnip;       }if(StringUtils.isBlank(ip) || UNKNOWN_VALUE.equalsIgnoreCase(ip)) {            ip = request.getHeader(PROXY_CLIENT_IP);       }if(StringUtils.isBlank(ip) || UNKNOWN_VALUE.equalsIgnoreCase(ip)) {            ip = request.getHeader(WL_PROXY_CLIENT_IP);       }if(StringUtils.isBlank(ip) || UNKNOWN_VALUE.equalsIgnoreCase(ip)) {            ip = request.getRemoteAddr();       } ​if(StringUtils.isBlank(ip) || UNKNOWN_VALUE.equalsIgnoreCase(ip)) {            ip = request.getHeader(HTTP_CLIENT_IP);       } ​if(StringUtils.isBlank(ip) || UNKNOWN_VALUE.equalsIgnoreCase(ip)) {            ip = request.getRemoteAddr();       }returnip.equals(LOCALHOST_V6) ? LOCALHOST_V4 : ip;   } ​ }

项目推荐:基于SpringBoot2.x、SpringCloud和SpringCloudAlibaba企业级系统架构底层框架封装,解决业务开发时常见的非功能性需求,防止重复造轮子,方便业务快速开发和企业技术栈框架统一管理。引入组件化的思想实现高内聚低耦合并且高度可配置化,做到可插拔。严格控制包依赖和统一版本管理,做到最少化依赖。注重代码规范和注释,非常适合个人学习和企业使用

Github地址:github/plasticene/…

Gitee地址:gitee/plasticene3…

3.获取ip归属地

通过上面我们就能获取到客户端用户的ip地址,接下来就可以通过ip解析获取归属地了。

如果我们在网上搜索资料教程,大部分都是说基于各大平台(eg:淘宝,新浪)提供的ip库进行查询,不过不难发现这些平台已经不怎么维护这个功能,现在处于半死不活的状态,根本不靠谱,当然有些平台提供可靠的获取ip属地接口,但是收费、收费、收费

本着作为一个程序员的严谨:能白嫖的就白嫖,避免出现要买的是你,不会用也是你的尴尬遭遇。扯远了言归正传,为了寻求可靠有效的解决方案,只能去看看github有没有什么项目能满足需求,果然功夫不负有心人,发现一个宝藏级项目:ip2region,一个准确率99.9%的离线IP地址定位库,0.0x毫秒级查询,ip2region.db数据库只有数MB的项目,提供了众多主流编程语言的 xdb 数据生成和查询客户端实现,这里只能说:开源真香,开源万岁。

3.1 Ip2region 特性

标准化的数据格式

每个 ip 数据段的 region 信息都固定了格式:国家|区域|省份|城市|ISP,只有中国的数据绝大部分精确到了城市,其他国家部分数据只能定位到国家,其余选项全部是0。

数据去重和压缩

xdb 格式生成程序会自动去重和压缩部分数据,默认的全部 IP 数据,生成的 ip2region.xdb 数据库是 11MiB,随着数据的详细度增加数据库的大小也慢慢增大。

极速查询响应

即使是完全基于 xdb 文件的查询,单次查询响应时间在十微秒级别,可通过如下两种方式开启内存加速查询:

vIndex 索引缓存 :使用固定的 512KiB 的内存空间缓存 vector index 数据,减少一次 IO 磁盘操作,保持平均查询效率稳定在10-20微秒之间。xdb 整个文件缓存:将整个 xdb 文件全部加载到内存,内存占用等同于 xdb 文件大小,无磁盘 IO 操作,保持微秒级别的查询效率。

IP 数据管理框架

v2.0 格式的 xdb 支持亿级别的 IP 数据段行数,region 信息也可以完全自定义,例如:你可以在 region 中追加特定业务需求的数据,例如:GPS信息/国际统一地域信息编码/邮编等。也就是你完全可以使用 ip2region 来管理你自己的 IP 定位数据。

99.9% 准确率

数据聚合了一些知名 ip 到地名查询提供商的数据,这些是他们官方的的准确率,经测试着实比经典的纯真 IP 定位准确一些。

ip2region 的数据聚合自以下服务商的开放 API 或者数据(升级程序每秒请求次数 2 到 4 次):

01,>80%,淘宝IP地址库,ip.taobao.com/%5C02,≈10%,GeoIP,geoip.com/%5C03,≈2%,纯真 IP 库,www.cz88.net/%5C

备注:如果上述开放 API 或者数据都不给开放数据时 ip2region 将停止数据的更新服务。

3.2 整合Ip2region客户端进行查询

提供了众多主流编程语言的 xdb 数据生成和查询客户端实现,已经集成的客户端有:java、C、php、c、python、nodejs、php扩展(php5 和 php7)、golang、rust、lua、lua_c,nginx。这里讲一下java的客户端。

首先我们需要引入依赖:

<dependency><groupId>org.lionsoul