通常我们在数据库中建立一个用户角色,是按照手机号、微信openId、支付宝账号等,来决定的。
但是最近呢,我们公司一个需求是希望通过获取用户内网独立的ip以及用户的机型来进行open install,以此来判定一个用户。
那么js如何获取用户的内网ip呢? 请看!

首先我们应该知道,普通的js是不具备获取ip的能力的,网上的一些网站比如ip138.com做的也是进入页面自动向后台发送请求,然后后台拿到请求,从请求头那里获取到用户的外网ip,但这毕竟是外网ip(也叫公网ip),如果是同一个公司的公网,或者是同一个校园班级等的公网就会导致一个问题:很多人都公用一个公网ip,那么这些人之中出现两个人用相同机型的可能性也是不低的,这样一来就会出现非常多的误判。
那么我是如何利用“权限比较低”的js来获取到用户的内网ip(也可以说是独立ip),并以此来精准定位到用户的呢?
没错,就是利用了webRTC这个技术,通过webRTC的api,来获取到带有ip、端口等信息的字符串,然后接下里就通过遍历端口,匹配内网ip地址的正则来获取到用户的内网ip。

需要声明一点:
webRTC是有兼容性的,它只能在较新版本的Chrome浏览器和firefox浏览器里才可以使用。
并且:手机的UC浏览器是不支持webRTC技术的,这样一来使用UC内核的其他手机浏览器也不可以使用webRTC技术来准确获取内网ip,
比如:小米手机MIUI系统自带浏览器目前使用的就是UC浏览器的内核。

下面是webRTC获取内网ip的代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
function getIPs(callback){
var ip_dups = {};
/* 判断是否兼容webRTC技术 */
var RTCPeerConnection = window.RTCPeerConnection || window.mozRTCPeerConnection || window.webkitRTCPeerConnection;
/* 是否是webkit内核下的webRTC 以此来判断是否是webkit或blink的内核 */
var useWebKit = !!window.webkitRTCPeerConnection;
/* 媒体限制 */
var mediaConstraints = { optional: [{RtpDataChannels: true}] };
/* stun服务器配置 */
var servers = {iceServers: [{urls: "stun:stun.services.mozilla.com"}]};
/* 实例化一个webRTC的对象 */
var pc = new RTCPeerConnection(servers, mediaConstraints);
function handleCandidate(candidate){
/* 用来判断内网ip的正则 */
var ip_regex = /([0-9]{1,3}(\.[0-9]{1,3}){3}|[a-f0-9]{1,4}(:[a-f0-9]{1,4}){7})/
var tt=ip_regex.exec(candidate);
/* 如果没有获取到内网ip 返回false */
if(tt==null||tt.length < 2){ return false; }
var ip_addr = tt[1];
/* 将获取到的内网ip放在回调函数参数 */
if(ip_dups[ip_addr] === undefined) callback(ip_addr);
/* 做一层保险 避免重复获取或返回 */
ip_dups[ip_addr] = true;
}
/* onicecandidate是RTC的示例pc上发生事件要调用的api */
pc.onicecandidate = function(ice){
if(ice.candidate) handleCandidate(ice.candidate.candidate);
};
pc.createDataChannel("");
pc.createOffer(function(result){
pc.setLocalDescription(result, function(){}, function(){});
}, function(){});
setTimeout(function(){
/* 遍历连接本地端的会话 */
var lines = pc.localDescription.sdp.split('\n');
/* 遍历判断是否存在candidate */
lines.forEach(function(line){
if(line.indexOf('a=candidate:') === 0) handleCandidate(line);
});
}, 1000);
}

参考:https://developer.mozilla.org/en-US/docs/Web/API/WebRTC_API