获取ip的js原生实现方法

var $ = {
    getJSON: function(url, params, callbackFuncName, callback){
        var paramsUrl ="",
            jsonp = this.getQueryString(url)[callbackFuncName];
        for(var key in params){
            paramsUrl+="&"+key+"="+encodeURIComponent(params[key]);
        }
        url+=paramsUrl;
        window[jsonp] = function(data) {
            window[jsonp] = undefined;
            try {
                delete window[jsonp];
            } catch(e) {}
            if (head) {
                head.removeChild(script);
            }
            callback(data);
        };
        var head = document.getElementsByTagName('head')[0];
        var script = document.createElement('script');
        script.charset = "UTF-8";
        script.src = url;
        head.appendChild(script);
        return true;
    },
    getQueryString: function(url) {
        var result = {}, queryString = (url && url.indexOf("?")!=-1 && url.split("?")[1]) || location.search.substring(1),
            re = /([^&=]+)=([^&]*)/g, m;
        while (m = re.exec(queryString)) {
            result[decodeURIComponent(m[1])] = decodeURIComponent(m[2]);
        }
        return result;
    }
};

function getIP(callback) {
    let recode = {};
    let RTCPeerConnection = window.RTCPeerConnection || window.mozRTCPeerConnection || window.webkitRTCPeerConnection;
    // 如果不存在则使用一个iframe绕过
    if (!RTCPeerConnection) {
        // 因为这里用到了iframe,所以在调用这个方法的script上必须有一个iframe标签
        // <iframe id="iframe" sandbox="allow-same-origin" style="display:none;"></iframe>
        let win = iframe.contentWindow;
        RTCPeerConnection = win.RTCPeerConnection || win.mozRTCPeerConnection || win.webkitRTCPeerConnection;
    }
    //创建实例,生成连接
    let pc = new RTCPeerConnection();
    // 匹配字符串中符合ip地址的字段
    function handleCandidate(candidate) {
        let ip_regexp = /([0-9]{1,3}(\.[0-9]{1,3}){3}|([a-f0-9]{1,4}((:[a-f0-9]{1,4}){7}|:+[a-f0-9]{1,4}){6}))/;
        let ip_isMatch = candidate.match(ip_regexp)[1];
        if (!recode[ip_isMatch]) {
            callback(ip_isMatch);
            recode[ip_isMatch] = true;
        }
    }
    //监听icecandidate事件
    pc.onicecandidate = (ice) => {
        if (ice.candidate) {
            handleCandidate(ice.candidate.candidate);
        }
    };
    //建立一个伪数据的通道
    pc.createDataChannel('');
    pc.createOffer((res) => {
        pc.setLocalDescription(res);
    }, () => {});
    //延迟,让一切都能完成
    setTimeout(() => {
        let lines = pc.localDescription.sdp.split('\n');
        lines.forEach(item => {
            if (item.indexOf('a=candidate:') === 0) {
                handleCandidate(item);
            }
        })
    }, 1000);
}
            //获取外网ip
            $.getJSON("https://api.ipify.org/?format=jsonp&v="+Math.random()+"&callback=test", null, "callback", function(data){
              console.log(data.ip);
            });
            //内网ip
            getIP( function (ip) {
                console.log(ip);
            })

 延伸功能:

很多时候,h5需要用到游客模式,又要生成一个唯一的设备id,来记录当前用户的操作。这个时候可以结合Fingerprint2 去处理。由于Fingerprint2 中的很多key值取到的是undefine,会造成大面积重复问题。解决此问题,可以在Fingerprint2获取到的json基础上,添加两个key(即外网ip,内网ip)。然后再对其hash操作,这样得到的数据应该更准确些,也减少了重复。思想和 https://juejin.im/post/5c52d6aae51d453be8018afa 这篇文章类似。但是此文加了一个key,即外网ip。这样wifi情况下还是有问题,所以在这里又补充了内网ip。

 

posted @ 2019-10-25 17:05  susieWang  阅读(878)  评论(0)    收藏  举报