近期有个需求,需要获取客户端Mac地址作为白名单验证的依据。使用.net,B/S架构。先百度找了一些获取mac地址的方法,

using System;
using System.Collections.Generic;
using System.Text;
using System.Text.RegularExpressions;
using System.IO;
using System.Net;
using System.Configuration;
using System.Web;
using System.Security.Cryptography;
using System.Data;
using System.Web.UI.WebControls;
using System.Management;
using System.Diagnostics;
using System.Net.NetworkInformation;
using System.Runtime.InteropServices; namespace Qianxun.Common
{
public class MacAddress
{
#region 获取mac地址的一些方法
#region 1 通过IPConfig命令读取MAC地址(选用)
/// <summary>
/// 根据截取ipconfig /all命令的输出流获取网卡Mac
/// </summary>
/// <returns></returns>
public static List<string> GetMacByIPConfig()
{
List<string> macs = new List<string>();
try
{
ProcessStartInfo startInfo = new ProcessStartInfo("ipconfig", "/all");
startInfo.UseShellExecute = false;
startInfo.RedirectStandardInput = true;
startInfo.RedirectStandardOutput = true;
startInfo.RedirectStandardError = true;
startInfo.CreateNoWindow = true;
Process p = Process.Start(startInfo);
// 截取输出流
StreamReader reader = p.StandardOutput;
string line = reader.ReadLine(); while (!reader.EndOfStream)
{
if (!string.IsNullOrEmpty(line))
{
line = line.Trim(); if (line.StartsWith("Physical Address") || line.StartsWith("物理地址"))
{
macs.Add(line.Substring(line.IndexOf(":") + 1, line.Length - line.IndexOf(":") - 1));
break;
}
} line = reader.ReadLine();
} // 等待程序执行完退出进程
p.WaitForExit();
p.Close();
reader.Close();
}
catch (Exception ex) { }
return macs;
}
#endregion #region 2 通过WMI读取MAC地址
/// <summary>
/// 通过WMI读取系统信息里的网卡MAC
/// 该方法依赖WMI的系统服务,该服务一般不会被关闭;但如果系统服务缺失或者出现问题,该方法无法取得MAC地址。
/// </summary>
/// <returns></returns>
public static List<string> GetMacByWMI()
{
List<string> macs = new List<string>();
try
{
string mac = "";
ManagementClass mc = new ManagementClass(" Win32_NetworkAdapterConfiguration ");
ManagementObjectCollection moc = mc.GetInstances();
foreach (ManagementObject mo in moc)
{
if ((bool)mo[" IPEnabled "])
{
mac = mo[" MacAddress "].ToString();
macs.Add(mac);
}
}
moc = null;
mc = null;
}
catch(Exception ex)
{
} return macs;
}
#endregion #region 3 通过NetworkInterface读取MAC地址:1)如果当前的网卡是禁用状态(硬件处于硬关闭状态),取不到该网卡的MAC地址,(您可以通过禁用网卡进行试验)。2)如果当前启用了多个网卡,最先返回的地址是最近启用的网络连接的信息
// 返回描述本地计算机上的网络接口的对象(网络接口也称为网络适配器)。
public static NetworkInterface[] NetCardInfo()
{
return NetworkInterface.GetAllNetworkInterfaces();
} /// <summary>
/// 通过NetworkInterface读取网卡Mac
/// </summary>
/// <returns></returns>
public static List<string> GetMacByNetworkInterface()
{
List<string> macs = new List<string>();
try
{
NetworkInterface[] interfaces = NetworkInterface.GetAllNetworkInterfaces();
foreach (NetworkInterface ni in interfaces)
{
macs.Add(ni.GetPhysicalAddress().ToString());
}
}
catch (Exception ex)
{ }
return macs;
}
#endregion
#region 4 通过SendARP读取MAC地址
/// <summary>
/// 通过SendARP获取网卡Mac
/// 网络被禁用或未接入网络(如没插网线)时此方法失灵
/// </summary>
/// <param name="remoteIP"></param>
/// <returns></returns>
public static string GetMacBySendARP(string remoteIP)
{
StringBuilder macAddress = new StringBuilder(); try
{
Int32 remote = inet_addr(remoteIP); Int64 macInfo = new Int64();
Int32 length = 6;
SendARP(remote, 0, ref macInfo, ref length); string temp = Convert.ToString(macInfo, 16).PadLeft(12, '0').ToUpper(); int x = 12;
for (int i = 0; i < 6; i++)
{
if (i == 5)
{
macAddress.Append(temp.Substring(x - 2, 2));
}
else
{
macAddress.Append(temp.Substring(x - 2, 2) + " - ");
}
x -= 2;
} return macAddress.ToString();
}
catch
{
return macAddress.ToString();
}
} [DllImport(" Iphlpapi.dll ")]
private static extern int SendARP(Int32 dest, Int32 host, ref Int64 mac, ref Int32 length);
[DllImport(" Ws2_32.dll ")]
private static extern Int32 inet_addr(string ip);
#endregion #region 5 从注册表读取MAC地址
//常规用户可通过读取注册表项Windows Genuine Advantage获取到物理网卡地址。
//1)如果注册表项被修改,则无法取得该MAC地址
//HKEY_LOCAL_MACHINE\Software\Microsoft\Windows Genuine Advantage
#endregion
#endregion
}
}

测试时猛然发现多个客户端获取到的mac地址都是一样的,惊觉获取的是服务端的Mac地址,服务端语言获取服务端Mac,那么我需要获取客户端Mac,应该使用客户端语言,最先想到的是js(因为有碰到过客户端ip和服务端ip的问题,这里倒也能想清楚)。百度了一圈,mac地址需要ActiveX脚本支持,

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>ie浏览器获取客户端Mac地址</title>
</head> <body> <object classid="CLSID:76A64158-CB41-11D1-8B02-00600806D9B6" id="locator" style="display: none; visibility: hidden"></object>
<object classid="CLSID:75718C9A-F029-11d1-A1AC-00C04FB6C223" id="foo" style="display: none; visibility: hidden"></object>
<form name="myForm">
<br />
MAC地址:<input type="text" name="macAddress">
</form>
</body>
</html> <script language="javascript">
var sMacAddr = "";
var sIPAddr = "";
var sDNSName = "";
var service = locator.ConnectServer();
service.Security_.ImpersonationLevel = 3;
service.InstancesOfAsync(foo, 'Win32_NetworkAdapterConfiguration');
</script>
<script for="foo" event="OnObjectReady(objObject,objAsyncContext)" language="JScript">
if (objObject.IPEnabled != null && objObject.IPEnabled != "undefined" && objObject.IPEnabled == true) {
if (objObject.IPEnabled && objObject.IPAddress(0) != null && objObject.IPAddress(0) != "undefined")
sIPAddr = objObject.IPAddress(0);
if (objObject.MACAddress != null && objObject.MACAddress != "undefined")
sMacAddr = objObject.MACAddress;
if (objObject.DNSHostName != null && objObject.DNSHostName != "undefined")
sDNSName = objObject.DNSHostName;
}
</script> <script for="foo" event="OnCompleted(hResult,pErrorObject, pAsyncContext)" language="JScript">
myForm.macAddress.value = sMacAddr;
</script> <script>
//判断浏览器是否支持ActiveX控件
//if (window.ActiveXObject) {
//支持-通过ActiveXObject的一个新实例来创建XMLHttpRequest对象
var WshShell = new ActiveXObject("WScript.Shell");
//}
//else {
// $("#tips").html("请使用ie并将本系统域名加入受信任的站点,并在internet选项-受信任的站点中开启ActiveX插件和脚本的相关权限");
//}
</script>

而这个东西仅支持ie,但是客户系统对ie兼容性不好,如果要调整,工作量巨大,那么就只能让其他浏览器比如chorme去兼容ActiveX。

1.首先找到chorme for ActiveX扩展插件,试了好几个版本,也依然无法获取到mac地址,不知道是我的使用方式有问题,还是这个方法已经失效。(chorme已经升级到当前最新版本 96.0.4664.45(正式版本) (64 位))。

2.之后找到IE Tab扩展插件,但是好像仅仅是在chorme上嵌入了一个ie内核,这样系统同样是不兼容的。

3.然后找到了油猴,想着写一个脚本获取mac地址存入c盘的一个txt文本,然后系统去读取这个txt文件即可。奈何油猴写了个alert(‘hello world‘)也没生效,不知道是使用方法有误,还是相关机制阻止了这种毫无意义的打扰。想到另一个问题,如果是后端去保存文件,其实是保存到服务器,而后端读取文件也需要客户端进行上传。而客户端脚本是没有权限去操作文件直接保存到txt(有点木马的特性,奈何没有涉及到这一块的技术)。所以该方案暂时搁置。

4.又找到一个插件PluginOK,但是是付费插件,原理应该是js调用c++去获取计算机物理信息,然后通过双向通信集成到系统。感觉有些大材小用,也没有这么多预算,暂时搁置,也没实测。这一痛点,成就了一家企业。

提取问题的根本矛盾点:mac地址仅支持ie获取,系统不兼容ie,那么就只能分成两步,1.ie获取mac 2.使用chorme登录系统操作,这1和2之间需要产生一个联系来把1获取的数据传递给2,想到上次微信扫码登录的逻辑,使用了预登陆机制,联想到暴雪的安全令机制,有了些许思路:

1.login页面创建一条预登陆记录存入数据库,且获取到id,在页面上拼接成安全令登录url

2.用户使用ie登录前一步拼接而成的url获取到mac地址且根据入参id存入到对应的数据库记录中(用户的ie需要先进行配置:1.ie浏览器internet选项-安全-受信任的站点将系统域名加入受信任的站点 2.还是刚才的地方 自定义级别 将ActiveX控件和插件相关权限打开)

3.返回原来的login页面输入账号密码即可登录,正常逻辑登录之后,配合预登陆id(可以从数据库获取mac地址)可以进行mac地址白名单的匹配

曲线救国,安全令增加一些交互效果,各处增加操作详细说明,倒也算勉强完成了需求

获取客户端Mac地址的更多相关文章

  1. js获取客户端MAC地址

    最近遇到一个需求,医院要求呼叫中心账号必须对应MAC地址,也就是说该MAC地址必须和呼叫中心账号对应才可使用,这可就难道我了,这需求就要求每次都判断用户登录的电脑MAC地址是否有呼叫中心账号,当然只针 ...

  2. js 获取客户端mac地址

    js 获取客户端mac地址 javascript获取客户端网卡MAC地址和IP地址和计算机名 nodesj如何获得客户端的mac地址呢? 浏览器获取MAC地址 不限浏览器的mac地址取得的几种办法 I ...

  3. java 通过ip获取客户端mac地址

    java 通过ip获取客户端mac地址 package com.asppro.util; import java.io.BufferedReader; import java.io.IOExcepti ...

  4. 如何获取客户端MAC地址(三个方法)

    方法一: 调用Windows的DOS命令,从输出结果中读取MAC地址: public static String getMACAddress() { String address = "&q ...

  5. php/js获取客户端mac地址的实现代码

    这篇文章主要介绍了如何在php与js中分别获取客户度mac地址的方法,需要的朋友可以参考下   废话不多讲,直接上代码吧! 复制代码 代码如下: <?php   class MacAddr {  ...

  6. http协议本身能获取客户端Mac地址问题

    http 位于网络应用程 应用层 会话层 表示层 传输层 网络层 数据链路层 物理层 数据在最高层开始传输 没经历下面一层加一层的头,然后传入目的电脑再进行一层层的解刨,所以http本来没有mac而接 ...

  7. web网站获取客户端mac地址

    <HTML><HEAD><TITLE>WMI Scripting HTML</TITLE> <META http-equiv=Content-Ty ...

  8. 关于获取客户端Mac地址

    private static string GetClientMAC() { string mac_dest = string.Empty; try { string strClientIP = Ht ...

  9. php获取客户端mac地址

    exec('/sbin/arp -a 2>&1', $array, $return_val);dump($array);$mac = '';foreach($array as $valu ...

随机推荐

  1. Java(10)认识类和对象

    作者:季沐测试笔记 原文地址:https://www.cnblogs.com/testero/p/15201574.html 博客主页:https://www.cnblogs.com/testero ...

  2. Java(19)接口知识及综合案例

    作者:季沐测试笔记 原文地址:https://www.cnblogs.com/testero/p/15201629.html 博客主页:https://www.cnblogs.com/testero ...

  3. windows右键菜单自动打包发布nuget,没有CI/CD一样方便!

    构建现代的 .Net 应用离不开 Nuget 的支持,而快速打包 Nuget 成了提高生产率的有效方法.没有CI/CD?来试试使用windows右键菜单吧 先看右键效果图 有时候我们可能没有CI/CD ...

  4. bash反弹shell

    part1:不求甚解的本地复现 攻击端Debian 10.x:  192.168.208.134 受害端Ubuntu : 192.168.208.135 攻击端打开(监听)某端口:  键入命令:[nc ...

  5. AIApe问答机器人项目Scrum Meeting博客汇总

    荡起双桨 Scrum Meeting 博客汇总 一.Alpha阶段 AIApe问答机器人Scrum Meeting 4.23 AIApe问答机器人Scrum Meeting 4.25 AIApe问答机 ...

  6. OO2020 助教工作总结

    1 我的初衷 这一学期的OO助教工作是我一段宝贵的经历,在其中我学习了很多.见识了很多,收获满满.当时报名OO的初衷主要有三方面.首先,我想说OO是我所上过的最好的一门课之一,这门课有这一套从理论讲授 ...

  7. linux与windows下文件编码问题

    注:转换操作均在Linux终端进行操作 DOS与Unix格式转换 安装工具:dos2unix.unix2dos # ubuntu apt-get install dos2unix apt-get in ...

  8. hdu 5100 Chessboard (额,,,,,就叫它趣味数学题吧)

    题意: 用K*1的砖块去覆盖N*N的大矩形,问最多能覆盖多少块. 详细证明:(转载自matrix67) Matrix67: The Aha Moments 趣题:用 k × 1 的矩形覆盖 n × n ...

  9. 中文NER的那些事儿4. 数据增强在NER的尝试

    这一章我们不聊模型来聊聊数据,解决实际问题时90%的时间其实都是在和数据作斗争,于是无标注,弱标注,少标注,半标注对应的各类解决方案可谓是百花齐放.在第二章我们也尝试通过多目标对抗学习的方式引入额外的 ...

  10. 『动善时』JMeter基础 — 56、JMeter使用命令行模式生成HTML测试报告

    目录 1.自动生成HTML图形化报告 2.使用已有的测试结果文件生成HTML报告 3.HTML图形化报告内容详解 (1)Dashboard页面:(重点查看) (2)Charts页面:(辅助分析) 4. ...