记录:通过第三方获取接口获取客户端IP,并判断当前IP是否在中国境内

前言

项目需要根据客户的ip判断当前是否在中国大陆境内访问前端系统,实现一定的业务。
通过第三方获取接口获取客户端IP,并判断当前IP是否在中国境内(不包括香港、台湾)。
当前文章记录完整的实现流程。
本文提供一种思路,如有其它需求可参考。

前置资源获取说明

  • 1、第三方接口获取IP资源
    • 网站:https://www.ipify.org/更多详细使用方式自行查阅
    • 在这里插入图片描述
      在这里插入图片描述
    • 当前网站也支持根据ip获取所属国家省市区等详细信息的接口,有免费付费的一些选项,但是我注册账号一直提示失败所以后来放弃了。
    • 在这里插入图片描述
  • 2、获取全世界各国家ip段区间数据:https://download.ip2location.com/lite/
  • 在这里插入图片描述
    • 在这里插入图片描述

    • 上图excel中的数据就是下载的csv数据,其中包含世界各国的ip段

    • 将上述excel进行筛选只保留CN的数据拷贝保存(如有需要香港台湾的自行筛选CN、HK、TW进行拷贝保存)

    • 将保存后的excel的第一行添加为 start end 如下图所示

    • 在这里插入图片描述

    • 然后全选拷贝至剪切板,之后在https://uutool.cn/excel2json/excel转json在线网站进行转换处理

    • 在这里插入图片描述

    • 将数据拷贝保存到新建的js文件中等待使用

    • 在这里插入图片描述

注意:ip区间段是有变化的,所以如果项目考虑到ip的实时变更问题,那就再找其它获取方式由后台定时读取进行缓存处理暴漏接口给到前端。

代码完整实现

1、引入jquery为了调用获取ip地址接口请求
2、引入上述保存的chinaIP.js文件

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>获取客户端ip 并判断是否在中国境内 不包含香港 台湾</title>
  <script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.6.1/jquery.js"></script>
  <script src="china_ip.js"></script>
</head>

<body>
  <h1 id="result"></h1>
  <script>

    // 参考资料
    // https://www.ipify.org/
    // https://geo.ipify.org/pricing
    // 全世界范围内ip段:https://lite.ip2location.com/database/ip-country
    // https://download.ip2location.com/lite/

    /**
    * https://api.ipify.org/
    * https://ipv4.icanhazip.com/
    * 两个地址均可获取当前访问系统的用户的ip地址,接口性能自行对比
    */

    // const start1 = new Date().getTime()
    // $.get("https://api.ipify.org/", function (data, status) { // 获取ip
    //   const diff = new Date().getTime() - start1
    //   document.querySelector('#ip1').innerHTML = 'ipv4:' + data + '----用时:' + diff
    // })


    // const start2 = new Date().getTime()
    // $.get("https://ipv4.icanhazip.com/", function (data, status) {
    //   const diff = new Date().getTime() - start2
    //   document.querySelector('#ip').innerHTML = 'ipv4:' + data + '----用时:' + diff
    //   console.log(ipToInt(data.trim())); // 获取到的ip后缀带空格 所以需要手动去掉
    // })

    // 接口调用获取ip
    $.get("https://ipv4.icanhazip.com/", function (ip, status) {
      const ipNum = ipToInt(ip.trim()) // 将xx.xx.xx.xx的ip转换成10进制的格式数值,用作和区间段做对比
      const atHome = isAtHome(chinaIp, ipNum) // 传入区间段和当前ip数值 判断返回是否查找到 找到则返回区间段的下标 否则返回-1
      if (atHome === -1) {
        // console.log('不在中国境内 包含香港 台湾');
        document.querySelector('#result').innerHTML = 'IP: ' + ip.trim() + '</br> result:不在中国境内 包含香港 台湾'
      } else {
        // console.log('在中国境内 不包含香港 台湾');
        document.querySelector('#result').innerHTML = 'IP: ' + ip.trim() + '</br> result:在中国境内 不包含香港 台湾'
      }
    })

    // 循环方式 判断ip是否在中国境内4000多个区间内
    // function isAtHome(ipNum) {
    //   console.log(chinaIp.length);
    //   let atHome = false // 不在国内
    //   // 此处查找可以使用二分法
    //   for (let i = 0; i < chinaIp.length; i++) {
    //     console.log(i);
    //     const ipArea = chinaIp[i]
    //     const s = Number(ipArea.start)
    //     const e = Number(ipArea.end)
    //     if (ipNum >= s && ipNum <= e) {
    //       atHome = true
    //       break
    //     }
    //   }
    //   return atHome
    // }

    // 二分 判断ip是否在中国境内4000多个区间内
    function isAtHome (nums, target) {
      let low = 0,
        high = nums.length - 1; //  下标
      while (low <= high) {
        const mid = Math.floor((high - low) / 2) + low;
        const num = nums[mid];
        if (target >= Number(num.start) && target <= Number(num.end)) {
          return mid;
        } else if (Number(num.start) > target) {
          high = mid - 1;
        } else {
          low = mid + 1;
        }
      }
      return -1;
    };


    // 将ip转换成10进制数字
    function ipToInt (ip) {
      var REG = /^(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])$/;
      var xH = "", result = REG.exec(ip);
      if (!result) return -1;
      return (parseInt(result[1]) << 24
        | parseInt(result[2]) << 16
        | parseInt(result[3]) << 8
        | parseInt(result[4])) >>> 0;
    }

  </script>
</body>

</html>

最终效果

在这里插入图片描述
在这里插入图片描述
完整流程皆由前端实现,如果有更好的方式,欢迎提供。

  • 3
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值