2019-04-23 11:21:53
ip地址是我们用来记录用户访问信息的一个重要标识,一方面我们可以用来防止某一个IP地址带来的大量DDOS攻击,通过判断来阻止此IP访问,这是其中一种手段。另外一个用途是用来定位,通过IP地址来获取用户的地理位置信息,我们可以描绘出大量的用户主要分布在哪些区域。
首先来说一下,如何通过nodejs来获取客户端的IP地址。
IP地址是分为IPV4和IPV6地址,在nodejs官网上有一个API:server.listen(),这个是启动服务器时所添加的。
server.listen([port][, host][, backlog][, callback])
````
启动一个TCP服务监听输入的 port 和 host.
如果 host 省略,如果 ipv6 可用,服务器将会接收基于 unspecified IPv6 address (::)的连接,否则接收 unspecified IPv4 address (0.0.0.0) 的链接。
客户请求的IP地址存在于request对象当中,所以获取的方式如下:
```javascript
var ip = req.headers['x-forwarded-for'] ||
req.ip ||
req.connection.remoteAddress ||
req.socket.remoteAddress ||
req.connection.socket.remoteAddress || '';
if(ip.split(',').length>0){
ip = ip.split(',')[0]
}
ip = ip.substr(ip.lastIndexOf(':')+1,ip.length);
上述代码是直接获取的IPV4地址,如果获取到的是IPV6,则通过字符串的截取来转换为IPV4地址。
上面我们已经获取到了IP地址,下面我们来看看如何来获取定位。
geoip-lite是GeoIP的精简版,MaxMind提供了一组用于IP到Geo映射的数据文件以及用于解析和查找这些数据文件的开源库。人们通常会在其C API周围编写一个包装器,以便以其他语言(如JavaScript)访问此数据。
GeoIP-lite试图成为一个完全原生的JavaScript库。转换器脚本将来自MaxMind的CSV文件转换为内部二进制格式(请注意,这与MaxMind提供的二进制数据格式不同)。geoip模块使用此二进制文件查找IP地址并返回其映射到的国家,地区和城市。
支持IPv4和IPv6地址,但由于GeoLite IPv6数据库当前不包含任何城市或地区信息,因此仅支持IPv4的城市,区域和邮政编码查找。
下面来看具体用法
1.首先是来安装:
npm install geoip-lite
2.使用 注意:geoip-lite是完全同步的。没有涉及回调。所有阻塞文件IO都在启动时完成,因此所有运行时调用都在内存中执行并且速度很快。启动可能需要200毫秒才能读入内存并索引数据文件。
var geoip = require('geoip-lite');
var ip = "60.222.230.50";
var geo = geoip.lookup(ip);
res.json(geo)
执行结果为:
返回结果中有几个重要的信息,其中country代表的是国家,region代表地区,比如说山西省,代号为SX,timezone指的是时区。其他的就不那么重要了。
3.另外这个插件内置了更新程序,可以从MaxMind中提取文件并处理CSV转换。已设置npm脚本别名以简化此过程。
cd node_modules/geoip-lite && npm run-script updatedb
//npm run-script updatedb force 强制更新
如果你的服务器正在使用geoip-lite的数据,更新完成之后并不需要重新启动,你可以在程序中重新加载更新后的数据
//同步
geoip.reloadDataSync();
//异步
geoip.reloadData(function(){
console.log("Done");
});
该方法的缺点在于一般情况下只能定位到省一级别,无法定位到城市级别。 具体的情况可查看他的GitHub
百度API获取IP地址有两种方式,一种是通过百度地图的IP定位接口获取,这种方式每日的请求次数以每秒并发量有一定的限制,同时不支持商业化应用,如果商业化需要缴纳年费,具体情况可以去百度开发者去查看。
这里说的是另一个百度的API,他就是在百度首页查询ip地址时调用的接口。
var urlquer="https://sp0.baidu.com/8aQDcjqpAAV3otqbppnN2DJv/api.php?query="+ip+"&co=&resource_id=6006&t=1555898284898&ie=utf8&oe=utf8&format=json&tn=baidu"
get_https_request(urlquer,function(data){
data.body = JSON.parse(data.body);
res.json(data)
})
这里我对https的请求做了一个封装,不在展示具体详细代码。返回的实际结果如下图所示:
这个接口的调用不知道是否可以用于商用,是否对单个IP地址的调用有限制,具体的可行性还需进一步验证,需谨慎使用。
另外该接口返回的结果中省市放在了一起,如果想单独拆分出来需要对其进行解析,如果是国外地址,则只返回国家。