你能通过JavaScript获得用户的本地局域网IP地址吗?

你能通过JavaScript获得用户的本地局域网IP地址吗?,javascript,ip-address,Javascript,Ip Address,我知道对这个问题的最初反应是“不”和“不可能”以及“你不应该需要它,你做错了”。我要做的是获取用户的局域网IP地址,并将其显示在网页上。为什么?因为这就是我正在处理的页面的全部内容,显示尽可能多的关于你的信息,访问者: 所以我实际上并没有对IP做任何事情,只是为了提供信息而向用户展示它。我过去常常使用一个小Java小程序来实现这一点。效果相当不错。但现在,浏览器让您多次点击“同意”和“信任”,甚至运行最小型的java小程序,我宁愿不运行一个 因此,有一段时间我刚刚摆脱了这个功能,但如果可能的话

我知道对这个问题的最初反应是“不”和“不可能”以及“你不应该需要它,你做错了”。我要做的是获取用户的局域网IP地址,并将其显示在网页上。为什么?因为这就是我正在处理的页面的全部内容,显示尽可能多的关于你的信息,访问者:

所以我实际上并没有对IP做任何事情,只是为了提供信息而向用户展示它。我过去常常使用一个小Java小程序来实现这一点。效果相当不错。但现在,浏览器让您多次点击“同意”和“信任”,甚至运行最小型的java小程序,我宁愿不运行一个

因此,有一段时间我刚刚摆脱了这个功能,但如果可能的话,我希望它能回来。作为一名计算机顾问,我会时不时地使用它。访问此网站查看网络运行的IP范围比进入系统首选项、网络以及任何活动接口都要快


所以我想知道,希望,是否有一些方法可以单独在javascript中实现?也许你可以访问一些新对象,就像javascript询问浏览器地球上的地理位置一样。也许客户端网络信息也有类似的功能?如果不是的话,也许还有其他方法可以完全做到这一点?我能想到的唯一方法是java小程序或flash对象。事实证明,最近HTML5的WebRTC扩展允许javascript查询本地客户端IP地址。此处提供了概念证明:


这个特性显然是错误的,不是错误。然而,考虑到它的争议性,我会对依赖这种行为持谨慎态度。尽管如此,我认为它完美且恰当地满足了您的预期目的(向用户透露他们的浏览器泄漏了什么)

更新

此解决方案将不再有效,因为浏览器正在修复webrtc泄漏:有关此问题的更多信息,请阅读其他问题:


除了afourney的回答之外,该代码还适用于支持WebRTC(Chrome和Firefox)的浏览器。我听说有一项运动正在实施一项使网站请求IP的功能(比如用户的地理位置或用户媒体),尽管这项功能尚未在这两种浏览器中实现

这是的一个修改版本,减少了行数,不进行任何眩晕请求,因为您只需要本地IP而不需要公共IP:

window.RTCPeerConnection = window.RTCPeerConnection || window.mozRTCPeerConnection || window.webkitRTCPeerConnection;//compatibility for Firefox and chrome
var pc = new RTCPeerConnection({iceServers:[]}), noop = function(){};      
pc.createDataChannel('');//create a bogus data channel
pc.createOffer(pc.setLocalDescription.bind(pc), noop);// create offer and set local description
pc.onicecandidate = function(ice)
{
 if (ice && ice.candidate && ice.candidate.candidate)
 {
  var myIP = /([0-9]{1,3}(\.[0-9]{1,3}){3}|[a-f0-9]{1,4}(:[a-f0-9]{1,4}){7})/.exec(ice.candidate.candidate)[1];
  console.log('my IP: ', myIP);   
  pc.onicecandidate = noop;
 }
};
我们正在创建一个虚拟对等连接,以便远程对等方与我们联系。我们通常相互交换ice候选,阅读ice候选,我们可以知道用户的ip


您可以在-->

上找到一个演示。您可以在-->上找到更多关于浏览器可能会增加哪些限制来缓解此问题的信息,以及IETF正在做什么,以及为什么需要这样做的信息
function getUserIP(onNewIP){//onNewIP-新IP的侦听器函数
//firefox和chrome的兼容性
var myPeerConnection=window.rtpeerconnection | | window.mozrtpeerconnection | | window.webkirtpeerconnection;
var pc=新的myPeerConnection({
ICEServer:[]
}),
noop=函数(){},
localIPs={},
ipRegex=/([0-9]{1,3}(\.[0-9]{1,3}){3}|[a-f0-9]{1,4}(:[a-f0-9]{1,4}){7})/g,
钥匙
函数迭代ip(ip){
如果(!localIPs[ip])onNewIP(ip);
localIPs[ip]=真;
}
onNewIP
//创建虚假数据通道
pc.createDataChannel(“”);
//创建报价并设置本地描述
pc.createOffer().then(函数(sdp){
sdp.sdp.split('\n').forEach(函数(行){
if(line.indexOf('candidate')<0)返回;
line.match(ipRegex).forEach(iterateIP);
});
pc.setLocalDescription(sdp、noop、noop);
}).catch(函数(原因){
//发生错误,请处理连接失败
});
//倾听候选事件
pc.onicecandidate=函数(ice){
如果(!ice | |!ice.candidate | |!ice.candidate.candidate | |!ice.candidate.candidate.match(ipRegex))返回;
ice.candidate.candidate.match(ipRegex.forEach)(iterateIP);
};
}

getUserIP(console.log)
我清理了mido的帖子,然后清理了他们找到的函数。这将返回
false
数组。测试时请记住,您需要在web developer控制台中折叠数组,否则它的非直观默认行为可能会欺骗您,使您认为它返回的是一个空的
数组

function ip_local()
{
 var ip = false;
 window.RTCPeerConnection = window.RTCPeerConnection || window.mozRTCPeerConnection || window.webkitRTCPeerConnection || false;

 if (window.RTCPeerConnection)
 {
  ip = [];
  var pc = new RTCPeerConnection({iceServers:[]}), noop = function(){};
  pc.createDataChannel('');
  pc.createOffer(pc.setLocalDescription.bind(pc), noop);

  pc.onicecandidate = function(event)
  {
   if (event && event.candidate && event.candidate.candidate)
   {
    var s = event.candidate.candidate.split('\n');
    ip.push(s[0].split(' ')[4]);
   }
  }
 }

 return ip;
}
此外,请大家记住,这不是像CSS
border radius
这样的老东西,尽管其中一个比特完全不受IE11和更老版本的支持。始终使用对象检测,在较旧的浏览器(如Firefox4、IE9、Opera 12.1)中进行测试,并确保新脚本不会破坏新代码。此外,始终首先检测符合标准的代码,因此如果存在CSS前缀之类的问题,则首先检测标准的无前缀代码,然后再返回,因为长期支持最终将在其剩余部分实现标准化。

可用于检索客户端的本地IP

但是,浏览器可能不支持它,或者客户端可能出于安全原因禁用了它。在任何情况下,都不应该长期依赖这种“黑客”,因为它很可能在未来得到修补(参见Cullen Fluffy Jennings的回答)

下面的ECMAScript 6代码演示了如何做到这一点

/* ES6 */
const findLocalIp = (logInfo = true) => new Promise( (resolve, reject) => {
    window.RTCPeerConnection = window.RTCPeerConnection 
                            || window.mozRTCPeerConnection 
                            || window.webkitRTCPeerConnection;

    if ( typeof window.RTCPeerConnection == 'undefined' )
        return reject('WebRTC not supported by browser');

    let pc = new RTCPeerConnection();
    let ips = [];

    pc.createDataChannel("");
    pc.createOffer()
     .then(offer => pc.setLocalDescription(offer))
     .catch(err => reject(err));
    pc.onicecandidate = event => {
        if ( !event || !event.candidate ) {
            // All ICE candidates have been sent.
            if ( ips.length == 0 )
                return reject('WebRTC disabled or restricted by browser');

            return resolve(ips);
        }

        let parts = event.candidate.candidate.split(' ');
        let [base,componentId,protocol,priority,ip,port,,type,...attr] = parts;
        let component = ['rtp', 'rtpc'];

        if ( ! ips.some(e => e == ip) )
            ips.push(ip);

        if ( ! logInfo )
            return;

        console.log(" candidate: " + base.split(':')[1]);
        console.log(" component: " + component[componentId - 1]);
        console.log("  protocol: " + protocol);
        console.log("  priority: " + priority);
        console.log("        ip: " + ip);
        console.log("      port: " + port);
        console.log("      type: " + type);

        if ( attr.length ) {
            console.log("attributes: ");
            for(let i = 0; i < attr.length; i += 2)
                console.log("> " + attr[i] + ": " + attr[i+1]);
        }

        console.log();
    };
} );
铬76+ 去年,我使用Linblow的答案(2018-10-19)通过javascript成功发现了我的本地IP。然而,最近的Chrome更新(76?)使该方法失效,因此它现在返回一个模糊的IP,例如:
1f4712db-ea17-4bcf-a596-105139dfd8bf.local

如果您可以完全控制浏览器,则可以通过关闭它来撤消此行为
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="utf-8">
    <title>Local IP</title>
</head>
<body>
    <h1>My local IP is</h1>
    <p id="ip">Loading..</p>
    <script src="ip.js"></script>
    <script>
    let p = document.getElementById('ip');
    findLocalIp().then(
        ips => {
            let s = '';
            ips.forEach( ip => s += ip + '<br>' );
            p.innerHTML = s;
        },
        err => p.innerHTML = err
    );
    </script>
</body>
</html>
chrome://flags