惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

小众软件
小众软件
A
About on SuperTechFans
博客园 - Franky
Engineering at Meta
Engineering at Meta
Recent Announcements
Recent Announcements
云风的 BLOG
云风的 BLOG
B
Blog
Microsoft Security Blog
Microsoft Security Blog
L
LangChain Blog
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
U
Unit 42
Martin Fowler
Martin Fowler
Y
Y Combinator Blog
Stack Overflow Blog
Stack Overflow Blog
博客园 - 叶小钗
Vercel News
Vercel News
Apple Machine Learning Research
Apple Machine Learning Research
The Cloudflare Blog
Last Week in AI
Last Week in AI
腾讯CDC
Microsoft Azure Blog
Microsoft Azure Blog
爱范儿
爱范儿
V
V2EX
G
Google Developers Blog

博客园 - 铭天

亲家网络的面试,请大家谨慎过去 redis命令String 安装redis RedHat6安装gcc Visual Studio 2015激活码,Visual Studio 2015密钥 从程序员到翻译的感受 .net中的浅拷贝和深拷贝 DataReader转实体<T> 关于.Net类型转换 Jquery传数组数据到Mvc后台 Silverlight TreeView控件的增删改查 Visual Studio 2010序列号 SilverLight3访问Wcf - 铭天 - 博客园 DataTable到范型转换 访问Oracle11g的.net组件 js特效和树 自定义WebPart菜单 JSChart控件 & Ajax 图片 SilverLight2CheckBox动态调用WebService
取客户MAP地址
铭天 · 2013-05-17 · via 博客园 - 铭天

最近在做电子政务,给某局以及直属单位做统一的用户登录功能。登录界面有多级选择列表,如:局单位-->局业务处室-->局用户-->用户名,每次登录都得这么选择,繁琐的操作对那些机关领导来说确实是一件不容易的事,为此就希望把用户选择的信息,初始化一次,以后登录就不用再选择那么多了。于是就想到记录客户端的MAC地址来做为机器标识。但要在客户端能快速准确的获取到MAC地址还是一件不太容易的事。主要常见的方式有以下几种:

方法一:Javascript结合系统的ActiveX

优点:无需开发额外的代码,轻量级的实现。不需要服务器端进行处理,有客户端自行获取,传递到服务器端,速度比在服务器端获取好。
缺点:受客服端平台的限制,如安全级别设置较高,则无常正常执行。还有情况就是可靠性不是怎么好,有获取不到的情况。

其实最关键的还是用到两个ActiveX:
<OBJECT id=locator classid=CLSID:76A64158-CB41-11D1-8B02-00600806D9B6 VIEWASTEXT></OBJECT>
<OBJECT id=foo classid=CLSID:75718C9A-F029-11d1-A1AC-00C04FB6C223></OBJECT>

两个ActiveX都是系统自带,不用去下载或注册。

  1. <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">  
  2.  
  3. <html>  
  4.     <head><title>WMI Scripting HTML</title>  
  5. <META http-equiv="Content-Type" content="text/html; charset=gb2312">  
  6. <script language="JScript" event="OnCompleted(hResult,pErrorObject, pAsyncContext)" for=foo>  
  7. document.forms[0].txtMACAddr.value=unescape(MACAddr);  
  8. document.forms[0].txtIPAddr.value=unescape(IPAddr);  
  9. document.forms[0].txtDNSName.value=unescape(sDNSName);  
  10.   
  11.   </script>  
  12.  
  13. <script language="JScript" event=OnObjectReady(objObject,objAsyncContext) for=foo>  
  14.    if(objObject.IPEnabled != null && objObject.IPEnabled != "undefined" && objObject.IPEnabled == true)  
  15.    {  
  16.     if(objObject.MACAddress != null && objObject.MACAddress != "undefined")  
  17.     MACAddr = objObject.MACAddress;  
  18.     if(objObject.IPEnabled && objObject.IPAddress(0) != null && objObject.IPAddress(0) != "undefined")  
  19.     IPAddr = objObject.IPAddress(0);  
  20.     if(objObject.DNSHostName != null && objObject.DNSHostName != "undefined")  
  21.     sDNSName = objObject.DNSHostName;  
  22.     }  
  23.   </script>  
  24.  
  25.     <META content="MSHTML 6.00.2800.1106" name=GENERATOR>  
  26. </head>  
  27. <body>  
  28. <object id=locator classid=CLSID:76A64158-CB41-11D1-8B02-00600806D9B6 VIEWASTEXT></object>  
  29. <object id=foo classid=CLSID:75718C9A-F029-11d1-A1AC-00C04FB6C223></object>  
  30.    <script language="JScript">  
  31.        var service = locator.ConnectServer();  
  32.        var MACAddr ;  
  33.        var IPAddr ;  
  34.        var DomainAddr;  
  35.        var sDNSName;  
  36.        service.Security_.ImpersonationLevel=3;  
  37.        service.InstancesOfAsync(foo, 'Win32_NetworkAdapterConfiguration');  
  38.    </script>  
  39.  
  40. <form  runat="server" id="formfoo" name="formbar" method="post">  
  41.     <input  name="txtMACAddr"/>  
  42.     <input  name="txtIPAddr"/>  
  43.     <input  name="txtDNSName"/>  
  44.     <asp:Button ID="Button1" runat="server" Text="Button" onclick="Button1_Click" />  
  45. </form>  
  46. </body>  
  47. </html> 

方法二:调用Win32API(推荐)

优点:成功率较高,不受客户浏览器的限制。
缺点:只能是Windows系统

Code

 private static string getIp()
 { 
     if (System.Web.HttpContext.Current.Request.ServerVariables["HTTP_VIA"] != null)   
      return System.Web.HttpContext.Current.Request.ServerVariables["HTTP_X_FORWARDED_FOR"].Split(new char[] { ',' })[0];      
    else  
      return System.Web.HttpContext.Current.Request.ServerVariables["REMOTE_ADDR"]; 
 }

  1.     [DllImport("Iphlpapi.dll")]  
  2.     private static extern int SendARP(Int32 dest, Int32 host, ref Int64 mac, ref Int32 length);  
  3.     [DllImport("Ws2_32.dll")]  
  4.     private static extern Int32 inet_addr(string ip);  
  5.  
  6. private string GetClientIP()  
  7.     {  
  8.         string result = HttpContext.Current.Request.ServerVariables["HTTP_X_FORWARDED_FOR"];  
  9.         if (null == result || result == String.Empty)  
  10.         {  
  11.             result = HttpContext.Current.Request.ServerVariables["REMOTE_ADDR"];  
  12.         }  
  13.  
  14.         if (null == result || result == String.Empty)  
  15.         {  
  16.             result = HttpContext.Current.Request.UserHostAddress;  
  17.         }  
  18.         return result;  
  19.     }  
  20.  
  21.  
  22.      
  23.      
  24.      
  25.      
  26.     public static string GetCustomerMac(string IP)  
  27.     {  
  28.         Int32 ldest = inet_addr(IP);  
  29.         Int64 macinfo = new Int64();  
  30.         Int32 len = 6;  
  31.         int res = SendARP(ldest, 0, ref macinfo, ref len);  
  32.         string mac_src = macinfo.ToString("X");  
  33.  
  34.         while (mac_src.Length < 12)  
  35.         {  
  36.             mac_src = mac_src.Insert(0, "0");  
  37.         }  
  38.  
  39.         string mac_dest = "";  
  40.  
  41.         for (int i = 0; i < 11; i++)  
  42.         {  
  43.             if (0 == (i % 2))  
  44.             {  
  45.                 if (i == 10)  
  46.                 {  
  47.                     mac_dest = mac_dest.Insert(0, mac_src.Substring(i, 2));  
  48.                 }  
  49.                 else 
  50.                 {  
  51.                     mac_dest = "-" + mac_dest.Insert(0, mac_src.Substring(i, 2));  
  52.                 }  
  53.             }  
  54.         }  
  55.  
  56.         return mac_dest;  
  57.     } 

方法三:后台进程调用nbtstat命令

优点:无需额外开发组件,不受客户端平台的限制
缺点:受网络范围的限制,成功率较低,速度慢。

具体实现原理:通过nbtstat -a IP 命令将对方计算机的信息输出管道,然后捕获管道输出的内容,再通过正则表达式将MAC筛选出来。

  1. public static string GetCustomerMac(string IP)  
  2. {  
  3.     string dirResults = "";  
  4.     ProcessStartInfo psi = new ProcessStartInfo();  
  5.     Process proc = new Process();  
  6.     psi.FileName = "nbtstat";  
  7.     psi.RedirectStandardInput = false;  
  8.     psi.RedirectStandardOutput = true;  
  9.     psi.Arguments = "-A " + IP;  
  10.     psi.UseShellExecute = false;  
  11.     proc = Process.Start(psi);  
  12.     dirResults = proc.StandardOutput.ReadToEnd();  
  13.     proc.WaitForExit();  
  14.     dirResults = dirResults.Replace("\r", "").Replace("\n", "").Replace("\t", "");  
  15.     Regex reg = new Regex("([0-9A-Fa-f]{2})(-[0-9A-Fa-f]{2}){5}", RegexOptions.IgnoreCase | RegexOptions.Compiled | RegexOptions.Multiline | RegexOptions.RightToLeft);  
  16.     Match mc = reg.Match(dirResults);  
  17.     if (mc.Success)  
  18.     {  
  19.         try 
  20.         {  
  21.             return mc.Groups[0].Value.ToString();  
  22.         }  
  23.         catch 
  24.         {  
  25.             return "";  
  26.         }  
  27.     }  
  28.     else 
  29.     {  
  30.         reg = new Regex("Host not found", RegexOptions.IgnoreCase | RegexOptions.Compiled);  
  31.         mc = reg.Match(dirResults);  
  32.         if (mc.Success)  
  33.         {  
  34.             return "Host not found!";  
  35.         }  
  36.         else 
  37.         {  
  38.             return "";  
  39.         }  
  40.     }