想过用js获取信息标识用户机器吗?获取本地ip?mac地址?
通过一番探索结论如下:
一、 mac地址不用想了。
二、 获取ip
我们知道nginx的配置X-Forwarded-For
后端可以拿到ip
,这个ip是出口ip,标识不了访问者机器
location /api {
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_connect_timeout 300;client_max_body_size 30m;
rewrite ^/wisbayar_api(.*)$ $1 break;
proxy_pass http://xx.xx.xx.xx:11001/;
}
三、利用webrtc
网页即时通信 功能 实现点对点
通信,获取ip,我们看代码如下。
function findIP(onNewIP) {
var myPeerConnection = window.RTCPeerConnection || window.mozRTCPeerConnection || window.webkitRTCPeerConnection;
var pc = new myPeerConnection({iceServers: [{urls: "stun:stun.l.google.com:19302"}]}),
noop = function() {},
localIPs = {},
ipRegex = /([0-9]{1,3}(\.[0-9]{1,3}){3}|[a-f0-9]{1,4}(:[a-f0-9]{1,4}){7})/g,
key;
function ipIterate(ip) {
if (!localIPs[ip]) onNewIP(ip);
localIPs[ip] = true;
}
pc.createDataChannel("");
pc.createOffer(function(sdp) {
sdp.sdp.split('\n').forEach(function(line) {
if (line.indexOf('candidate') < 0) return;
line.match(ipRegex).forEach(ipIterate);
});
pc.setLocalDescription(sdp, noop, noop);
}, noop);
pc.onicecandidate = function(ice) {
console.log('ice.candidate', ice.candidate)
if (!ice || !ice.candidate || !ice.candidate.candidate || !ice.candidate.candidate.match(ipRegex)) return;
ice.candidate.candidate.match(ipRegex).forEach(ipIterate);
};
}
function addIP(ip) {
console.log('got ip: ', ip);
}
findIP(addIP)
上面的代码提到的概念有点多,我们通过代码逐步看一下点对点通信概念:
new myPeerConnection({iceServers: [{urls: "stun:stun.l.google.com:19302"}]}),
-
先看这里
iceServers
是什么?
ICE(Interactive Connectivity Establishment)
:是一个框架,允许您的 Web 浏览器 (一个Peer A)与对等方(另一个Peer B)连接,它需要绕过阻止打开连接的防火墙,内网限制。如果您的路由器不允许您直接与对等方连接,则通过服务器中继数据。 而ICE
使用STUN
/TURN
的一些技术来实现此目的
实现点对点
通信,实例名取RTCPeerConnection
,就好理解了。 -
代码里的
stun.l.google.com:19302
是什么?
这是google的STUN
服务器。这里还有很多公益的免费的可以查看:其他公共STUN 或 TURN 服务器
当然如果你要做自己的视频功能,你也可以替换为自己的服务。
长这个样子.png如果我们这里不写这个
STUN
服务器,在pc.onicecandidate
中打印ice.candidate. address
可以看到 是一个以.local
结尾的字符串而不是自己想要的IP。
- 那
STUN
服务器干了什么呢?
STUN(Session Traversal Utilities for NAT )
是一种协议。客户端将向 Internet 上的 STUN 服务器发送请求,该服务器将回复客户端的公共IP以及客户端是否可以在NAT
后面访问
-
NAT
是什么?
NAT(Network Address Translation)
:为设备提供公共IP
地址,俗称路由器。 给局域网内部分配内网地址,对外就使用它的公共IP
地址。
但是,某些路由器对谁可以连接到网络上的设备有限制,即使我们有STUN
服务器找到的公共IP
地址,也不是任何人都可以创建连接。在这种情况下,我们需要转向TURN
。 -
再看
TURN
是什么?
TURN(Traversal Using Relays around NAT)
:围绕 NAT 使用中继遍历,实际上就是NAT
路由器限制了不能直连,就使用TURN
服务器来中转转发,是一种降级方式。
结合上面的图,现在我们就明白了,为了实现无延迟,实时通信,就要通过绕过
NAT
的限制,达到直连机器的目的。如果不能直连,就使用TURN
中转。
STUN
服务器是用来取外网地址的。
TURN
服务器是在P2P(点对点)失败时进行转发的
- 代码里
pc.createDataChannel
,pc.createOffer
是什么意思?
pc.createDataChannel
是创建了一个数据通道,这是在建立连接之前交换信息的通信渠道。需要需要交换的信息是一端发送Offer(pc.createOffer)
和远端响应Answer (remote.createAnswer)
。交换的信息就是sdp
-
sdp
是什么?
SDP (Session Description Protocol)
用于描述多媒体会话,以便进行会话通知、会话邀请和其他形式的多媒体会话启动。在启动多媒体电话会议、IP 语音呼叫、流式视频或其他会话时,需要向参与者传达媒体详细信息、传输地址和其他会话描述元数据。
- 交换
sdp
信息后,两边还必须交换有关网络连接的信息,pc.onicecandidate
就是干这个的
ICE candidate
直接翻译:ice 候选人。这个pc.onicecandidate
方法就说明了两边通信是直连还是说要通过 TURN
服务器中继。这个方法里就能得到公共IP
到这里,我们就了解了获取
IP
代码的意思。拿到了公共IP
,至于内网IP
,浏览器做了限制,放开限制才能拿到, 以下是不同浏览器放开限制的方法
火狐(FireFox) 删除隐藏IP
浏览器输入 about:config
搜索配置 media.peerconnection.enabled 改为false ( 刷新程序,IP正常显示 )
谷歌(Chrome) 删除隐藏IP
浏览器输入:chrome://flags/#enable-webrtc-hide-local-ips-with-mdns
把 Anonymize local IPs exposed by WebRTC 设置为 disabled ( 刷新程序,IP正常显示 )
edge浏览器删除隐藏ip
浏览器输入: edge://flags/#enable-webrtc-hide-local-ips-with-mdns
把 Anonymize local IPs exposed by WebRTC 设置为 disabled ( 刷新程序,IP正常显示 )
四、 使用设备指纹
首先可以想到的是使用uuid
生成一个放在本地,但是不够固定。删了本地存的,在浏览器版本未变的情况下就又生成了一个新的。
npm 上的fingerprintjs
这个指纹信息可以是字体、canvas、插件、屏幕分辨率、时区、地理位置或者是你使用的语言等其他的参数,信息越多并且信息的区别度越大,越能决定浏览器指纹的准确性。
在高版本要获得许可了,可以使用免费的低版本版本。
实测使用它在不同机器上,相同版本浏览器下生成唯一id
是不一样的,似乎可用。
依然要注意以下问题:
- 升级浏览器后,
id
会变 (重装浏览器,大概率版本号也变了) - 稳定性,这个
id
会持续多久。文档提到免费版维持几周 - 不同的浏览器生成的
id
是不一样的。
这里我在登陆时生成一次后,存在本地。后续登陆不再生成,并结合浏览器名称和版本,作为唯一标识id
。基本满足使用场景来判断这个用户是否在另一个人的机器上登陆过
网友评论