如何仅使用纯js获取手机内网和外网IP地址

如何仅使用纯js获取手机内网和外网IP地址


js虽然无法直接获取手机IP地址,但是Javascript能够创建Http请求,并且服务器端语言能够检索用户公共IP。换句话说,如果您要检索用户的公共IP,则 必须从请求到任何服务器的依赖,以便检索IP。但是,随着WebRTC的引入,您将能够使用RTCPeerConnection技巧性地检索用户的私有IP。

在本文中,您将学习如何通过一些技巧轻松地检索用户IP(使用纯JavaScript的私有IP和使用第三方服务的公共IP)。

一、使用webRTC(获取内网IP)


RTCPeerConnection接口允许您在计算机和远程对等方之间创建WebRTC连接,我们可以使用他来实现js获取手机内网IP。

createOffer方法会启动会话描述协议(SDP)的创建,该协议提供有关附加到WebRTC会话的任何MediaStreamTrack,会话,代码以及ICE代理已经收集的任何候选者的信息(包含我们的目标IP)。

在旧版本中,此方法使用回调。但是,现在返回一个基于Promise的值,该值将在获取后返回我们需要的信息:

<script type="text/javascript">
    /**
    * Get the user IP throught the webkitRTCPeerConnection
    * @param onNewIP {Function} listener function to expose the IP locally
    * @return undefined
    */
    function getUserIP(onNewIP) {
        //  onNewIp - your listener function for new IPs
        //compatibility for firefox and chrome
        var myPeerConnection = window.RTCPeerConnection || window.mozRTCPeerConnection || window.webkitRTCPeerConnection;
        var pc = new myPeerConnection({
            iceServers: []
        }),
        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 iterateIP(ip) {
            if (!localIPs[ip]) onNewIP(ip);
            localIPs[ip] = true;
        }

        //create a bogus data channel
        pc.createDataChannel("");

        // create offer and set local description
        pc.createOffer().then(function(sdp) {
            sdp.sdp.split('\n').forEach(function(line) {
                if (line.indexOf('candidate') < 0) return;
                line.match(ipRegex).forEach(iterateIP);
            });

            pc.setLocalDescription(sdp,
                noop,
                noop);
        }).catch(function(reason) {
            // An error occurred, so handle the failure to connect
        });

        //listen for candidate events
        pc.onicecandidate = function(ice) {
            if (!ice || !ice.candidate || !ice.candidate.candidate || !ice.candidate.candidate.match(ipRegex)) return;
            ice.candidate.candidate.match(ipRegex).forEach(iterateIP);
        };
    }

    // Usage

    getUserIP(function(ip) {
        alert("Got IP! :" + ip);
    });

</script>


注意:改方法将返回手机内网IP而不是公共外网IP。

二、使用第三方服务(获取外网IP)


如果要获取外网公共ip地址,则将无法使用RTCPeerConnection了,需要借助第三方的服务。

1、不安全的连接HTTP

要从没有SSL证书的网站获取用户的IP,可以依靠ipinfo.io。该服务提供了一个API,可通过一个简单的ajax调用来获取客户端IP:

$.getJSON('http://ipinfo.io', function(data){
     console.log(data);
});


检索到的数据对象包含本地化信息,例如:国家/地区,城市等(如果可用)。ipinfo的服务器使用基于延迟的DNS路由来尽可能快地处理请求。


2、安全连接HTTPS(推荐)

要从网站获取用户的IP,甚至在具有SSL的安全网站中,也可以使用ipify服务,该服务提供了友好的API,可以轻松获取用户IP。该服务没有请求限制。

您可以在请求API的项目中使用它(如果需要,可以使用format参数),然后就可以开始使用了。

API URI 回应类型 样本输出(IPv4) 样本输出(IPv6)

https://api.ipify.org text 11.111.111.111 ?
https://api.ipify.org?format=json json {"ip":"11.111.111.111"} ?
https://api.ipify.org?format=jsonp jsonp callback({"ip":"11.111.111.111"}); ?
https://api.ipify.org?format=jsonp&callback=getip jsonp getip({"ip":"11.111.111.111"}); ?


您可以将其与JSONP一起使用:

<script type="application/javascript">
function getIP(json) {
     document.write("My public IP address is: ", json.ip);
}
</script>
<script type="application/javascript" src="https://api.ipify.org?format=jsonp&callback=getIP"></script>


或使用jQuery检索带有json请求的对象:

$.getJSON('https://api.ipify.org?format=json', function(data){
    console.log(data.ip);
});


此外,如果您拥有自己的服务器并且能够使用它,则可以创建自己的私有服务,该私有服务使用诸如PHP,ASP.NET等服务器语言返回用户的IP。以PHP为例

<?php
function getip() {

  static $ip = '';

  $ip = $_SERVER['REMOTE_ADDR'];

  if(isset($_SERVER['HTTP_CDN_SRC_IP'])) {

    $ip = $_SERVER['HTTP_CDN_SRC_IP'];

  } elseif (isset($_SERVER['HTTP_CLIENT_IP']) && preg_match('/^([0-9]{1,3}\.){3}[0-9]{1,3}$/', $_SERVER['HTTP_CLIENT_IP'])) {

    $ip = $_SERVER['HTTP_CLIENT_IP'];

  } elseif(isset($_SERVER['HTTP_X_FORWARDED_FOR']) AND preg_match_all('#\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}#s', $_SERVER['HTTP_X_FORWARDED_FOR'], $matches)) {

    foreach ($matches[0] AS $xip) {

      if (!preg_match('#^(10|172\.16|192\.168)\.#', $xip)) {

        $ip = $xip;

        break;

      }

    }

  }

  return $ip;

}
echo getip();



{{collectdata}}

网友评论0