2019独角兽企业重金招聘Python工程师标准>>>

参考网页:

  • http://stackoverflow.com/questions/391979/how-to-get-clients-ip-address-using-javascript-only
  • https://github.com/diafygi/webrtc-ips
  • http://www.yiichina.com/tutorial/459
  • http://www.html-js.com/article/Learn-JavaScript-every-day-to-understand-what-JavaScript-Promises

构思

通过 PHP 获得的客户端本地 IP 地址,往往不正确,在局域网内含有子网的时候,特别不方便,但是 javascript 可以读取本地的 IP 地址。 设想 javascript 把读取的 IP 地址传过来。最好的办法是采用 ajax 的方式传回。但是这个方法有局限性。做到代码里,不好直接使用,而且耦合特别严重,不适合再次使用。想了好久,最后用 InputWidget 的方式实现了。这个有一个非常不好的地方是,这个IP是可以被浏览器修改的,安全性完全没有保障。不过 ajax 的方式传回数据依旧会被修改。不如这么简单省事点。

代码实现

thanks to WebRTC, it is very easy to get local IP in WebRTC supported browsers( at least for now). I have modified the source code, reduced the lines, not making any stun requests since you only want Local IP not the Public IP, the below code works in latest Firefox and Chrome, just run the snippet and check for yourself:

function findIP(onNewIP) { //  onNewIp - your listener function for new IPsvar myPeerConnection = window.RTCPeerConnection || window.mozRTCPeerConnection || window.webkitRTCPeerConnection; //compatibility for firefox and chromevar 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 ipIterate(ip) {if (!localIPs[ip]) onNewIP(ip);localIPs[ip] = true;}pc.createDataChannel(""); //create a bogus data channelpc.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); // create offer and set local descriptionpc.onicecandidate = function(ice) { //listen for candidate eventsif (!ice || !ice.candidate || !ice.candidate.candidate || !ice.candidate.candidate.match(ipRegex)) return;ice.candidate.candidate.match(ipRegex).forEach(ipIterate);};
}var ul = document.createElement('ul');
ul.textContent = 'Your IPs are: '
document.body.appendChild(ul);function addIP(ip) {console.log('got ip: ', ip);var li = document.createElement('li');li.textContent = ip;ul.appendChild(li);
}findIP(addIP);

一个简单的例子

<html>
<body>
</body>
<script type="text/javascript">
function findIP(onNewIP) { //  onNewIp - your listener function for new IPsvar myPeerConnection = window.RTCPeerConnection || window.mozRTCPeerConnection || window.webkitRTCPeerConnection; //compatibility for firefox and chromevar 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 ipIterate(ip) {if (!localIPs[ip]) onNewIP(ip);localIPs[ip] = true;}pc.createDataChannel(""); //create a bogus data channelpc.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); // create offer and set local descriptionpc.onicecandidate = function(ice) { //listen for candidate eventsif (!ice || !ice.candidate || !ice.candidate.candidate || !ice.candidate.candidate.match(ipRegex)) return;ice.candidate.candidate.match(ipRegex).forEach(ipIterate);};
}var ul = document.createElement('ul');
ul.textContent = 'Your IPs are: '
document.body.appendChild(ul);function addIP(ip) {console.log('got ip: ', ip);var li = document.createElement('li');li.textContent = ip;ul.appendChild(li);
}findIP(addIP);
</script>
</html>

功能设想

为了在 Yii 2.0 中使用该功能,很方便的使用,最好做成插件的形式。代码可否简化?能跟 PHP 很好的对接吗? 先跟 PHP 对接,然后考虑放到 Yii 2.o 中。使用不断试错的方法来实现。

1、怎么把检测到的 IP 地址传回来?

第一想法是采用 ajax 的方式,在服务器端接收该 IP 地址。问题是把 ajax 的代码放在哪里呢?其中的 onNewIP 是个不错的突破口。 下面开始对代码进行第一次试错。

function findIP(onNewIP) { //  onNewIp - your listener function for new IPs
// 略
}function writeIP(ip) {document.write(ip);document.close();
}findIP(writeIP);

解释

  • 本打算使用 ajax 的方式,但是还需要一个回调函数,太复杂了。
  • 在 widget 里没有找到加入 actionCallBack 的方法。
  • 遂采用直接打印输出的方式回传。

2、做成 InputWidget 类

参考:

  • http://www.yiichina.com/tutorial/459

下面是怎么修改了。

3、中间过程不说了,下面把可以运行的代码贴下来。

我使用的高级模板,把这些代码放在了三个文件里。分别是

common\assets\WebRTCLocalIPAsset.phpjs\webrtclocalip.jscomponents\WebRTCLocalIPWidget.php

三个文件的代码如下

./common/assets/js/webrtclocalip.js

var id = 'webrtclocalip';function setoptions(options){id=options.id;
}function findIP(onNewIP) { //  onNewIp - your listener function for new IPsvar promise = new Promise(function (resolve, reject) {try {var myPeerConnection = window.RTCPeerConnection || window.mozRTCPeerConnection || window.webkitRTCPeerConnection; //compatibility for firefox and chromevar 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 ipIterate(ip) {if (!localIPs[ip]) onNewIP(ip);localIPs[ip] = true;}pc.createDataChannel(""); //create a bogus data channelpc.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); // create offer and set local descriptionpc.onicecandidate = function (ice) { //listen for candidate eventsif (ice && ice.candidate && ice.candidate.candidate && ice.candidate.candidate.match(ipRegex)) {ice.candidate.candidate.match(ipRegex).forEach(ipIterate);}resolve("FindIPsDone");return;};}catch (ex) {reject(Error(ex));}});// New Promise(...{ ... });return promise;
};//This is the callback that gets run for each IP address found
function foundNewIP(ip) {if (typeof window.ipAddress === 'undefined'){window.ipAddress = ip;}else{window.ipAddress += " - " + ip;}
}function load() {//This is How to use the Waitable findIP function, and react to the//results arrivingvar ipWaitObject = findIP(foundNewIP);        // Puts found IP(s) in window.ipAddressipWaitObject.then(function (result) {// for not hiddendocument.getElementById(id).textContent = window.ipAddress;// for hiddendocument.getElementById(id).value = window.ipAddress;},function (err) {alert ("无法找到 IP 地址" + err)});
}

./common/assets/WebRTCLocalIPAsset.php

<?phpnamespace common\assets;use yii\web\AssetBundle;class WebRTCLocalIPAsset extends AssetBundle
{public $sourcePath = '@common/assets';public $css = [];public $js = ['js/webrtclocalip.js',];
}

./common/components/WebRTCLocalIPWidget.php

<?php
namespace common\components;use yii\widgets\InputWidget;
use Yii;
use yii\helpers\Html;
use yii\helpers\Url;
use common\assets\WebRTCLocalIPAsset;class WebRTCLocalIPWidget extends InputWidget
{public $localip;public $hidden = true;public $attributes;public $id = 'webrtclocalip';public $name = 'webrtclocalip';public function init(){parent::init();}public function run(){$view = $this->getView();$this->attributes['id'] = $this->id;if ($this->hasModel()) {if ($this->hidden) {$input = Html::activeHiddenInput($this->model, $this->attribute, $this->attributes);} else {$input = Html::activeTextInput($this->model, $this->attribute, $this->attributes);}} else {if ($this->hidden) {$input = Html::hiddenInput($this->name, '', $this->attributes);} else {$input = Html::textInput($this->name, '', $this->attributes);}}echo $input;WebRTCLocalIPAsset::register($view);$view->registerJs("setoptions({id: '" . $this->id . "'});load();");}
}

4、用法

类似一般的 widget

        <?= $form->field($model, 'ip')->label(false)->widget(WebRTCLocalIPWidget::className(), ['id' => 'loginform-ip','hidden' => true,]) ?>

解释

  • WebRTCLocalIPWidget::className() 需要使用 use 语句
  • 'id' => 'loginform-ip', 需要查看网页代码检测该插件的 id,然后写入。这个暂时没有找到好的解决方案。

后期

正在把他作为一个插件,敬请期待

https://github.com/bubifengyun/yii2-webrtc-get-client-local-ip

转载于:https://my.oschina.net/bubifengyun/blog/690253

javascript 获得本地 IP 地址相关推荐

  1. 通过js获取本地IP地址

    通过js获取本地IP地址 最近在做pc项目,需要根据用户的IP地址定位城市.IP地址需要通过js获取: 网上有很多查询接口可以获取到IP,我这里用的是搜狐的: http://pv.sohu.com/c ...

  2. python在windows和linux_python在windows和linux下获得本机本地ip地址方法小结

    本文实例总结了python在windows和linux下获得本机本地ip地址方法.分享给大家供大家参考.具体分析如下: python的socket包含了丰富的函数和方法可以获得本机的ip地址信息,so ...

  3. python输入ip地址_python批量生成本地ip地址的方法

    本文实例讲述了python批量生成本地ip地址的方法.分享给大家供大家参考.具体分析如下: 这段代码用于在本地计算机上生成本地ip地址绑定到网卡,生成的是一个bat的批处理文件,运行此批处理文件,可以 ...

  4. c#获取本地ip地址网关子网掩码_教你如何修改路由器LAN口IP地址的方法

    现在绝大部分品牌或非品牌有线或无线路由器,其LAN口地址一般使用192.168.1.1或192.168.0.1网段,而使用此默认地址,既不安全,有时也不实用,比如局域网中电脑数过高,超过255台,则此 ...

  5. //获取本地IP地址和对端IP地址

    1 //获取本地IP地址 2 CHAR * GetLocalIpAdrr(int fd) 3 { 4 struct sockaddr_in stHost; 5 memset(&stHost, ...

  6. 获取本地ip地址适用于windows和Linux环境

    简写版本 package com.gblfy.util;import java.net.Inet4Address; import java.net.InetAddress; import java.n ...

  7. Linux下编程获取本地IP地址的常见方法

    代码编译运行平台:Linux 64bits+g++(-m64),-m64表示生成64bits的程序. 在进行Linux网络编程时,经常用到本机IP地址.本文罗列一下常见方法,以备不时之需. 获取本机I ...

  8. 如何查看本地ip地址和外网地址

    这是查看本地ip地址 这是查看外网ip地址

  9. android 获取wifi的ip地址吗,Android开发实现在Wifi下获取本地IP地址的方法

    本文实例讲述了Android开发实现在Wifi下获取本地IP地址的方法.分享给大家供大家参考,具体如下: 代码核心介绍: WifiManager类提供了对设备Wifi功能的管理,包括Wifi开关的打开 ...

  10. 如何获得使用PHP的服务器的本地IP地址?

    ​ 我正在开发一个只能在本地networking上运行的PHP应用程序. 应用程序将使用自定义安装程序安装到服务器,就像使用Stunnix高级Web服务器所做的一样. 作为使应用程序更加用户友好的一部 ...

最新文章

  1. Ruby 2.2.0发布,支持增量式垃圾收集和符号的垃圾收集
  2. KVM创建虚拟机(六)
  3. webpack打包vue反编译_2020年你必须知道的webpack打包优化方法
  4. 你所知道的都是错的!产品经理的十大认知错误
  5. 隐藏导航栏或返回按钮
  6. java 计算机开始时间,关于计算Java程序运行时间
  7. 【Python】strip()方法
  8. Mongodb学习总结(1)——常用NoSql数据库比较
  9. ActiveMQ学习总结(6)——ActiveMQ集成Spring和Log4j实现异步日志
  10. 《Java安全编码标准》一2.11 IDS10-J不要拆分两种数据结构中的字符串
  11. JS原型链原理(链表)
  12. R语言模型中的加总偏误与内生性:一种数值模拟方法
  13. 超全深度学习细粒度图像分析:项目、综述、教程一网打尽
  14. 回溯法求解TSP问题(旅行商问题)
  15. 2018年上半年信息系统项目管理师考试真题附答案解析(1)
  16. Codeforces Gym 100015B Ball Painting 找规律
  17. 2023年湖南中专单招报名流程
  18. 简单使用SAXReader解析xml数据
  19. 阿里高级外包你待得住吗?
  20. C#实现简单的网游客户端编程

热门文章

  1. paip.invalid conversion from FormWdg* to SOCKET {aka unsigned int}
  2. (转)比特币基金难产 区块链基金成首发
  3. “阿里云开放平台俱乐部”首站启航
  4. 【优化分类】基于matlab GA优化GRNN超参数分类【含Matlab源码 1399期】
  5. 【人脸识别】基于matlab GUI PCA人脸识别【含Matlab源码 748期】
  6. python to datetime_Python中缺少datetime.timedelta.to_seconds()-float?
  7. 从零开始带你成为消息中间件实战高手_系统化开课了,电子入门一切从零开始,喜欢电子的有机会学习了...
  8. 采矿协议_采矿电信产品推荐
  9. 什么是AsHelper
  10. Serilog输出日志到mysql_ASP.NET Core利用Docker ElasticSearch Kibana来记录日志