MAC 地址屬於資料鏈路層 (Layer 2) 識別碼,無法跨越路由器 (Layer 3) 傳輸。因此:
本文提供程式碼參考,並強調適用場景與安全風險。
原理:伺服器收到請求後,從 $_SERVER['REMOTE_ADDR'] 取得客戶端 IP,執行系統指令查詢本機 ARP 快取或 NetBIOS 表。
<?php
class MacAddr {
public $returnArray = [];
public $macAddr = '';
public function __construct($os_type = null) {
if (is_null($os_type)) $os_type = PHP_OS;
switch (strtolower($os_type)) {
case 'linux': $this->forLinux(); break;
case 'windows': default: $this->forWindows(); break;
}
$this->parseMac();
}
private function forWindows() {
@exec("ipconfig /all", $this->returnArray);
if (!$this->returnArray) {
$ipconfig = $_SERVER["WINDIR"] . "\\system32\\ipconfig.exe";
@exec($ipconfig . " /all", $this->returnArray);
}
}
private function forLinux() {
@exec("ifconfig -a", $this->returnArray);
}
private function parseMac() {
$pattern = '/[0-9a-f]{2}[:-][0-9a-f]{2}[:-][0-9a-f]{2}[:-][0-9a-f]{2}[:-][0-9a-f]{2}[:-][0-9a-f]{2}/i';
foreach ($this->returnArray as $line) {
if (preg_match($pattern, $line, $m)) {
$this->macAddr = $m[0];
break;
}
}
}
}
// 獲取伺服器自身網卡 MAC (示範)
$mac = new MacAddr(PHP_OS);
echo "Server MAC: " . $mac->macAddr . "<br/>";
// 獲取「同網段」客戶端 MAC
$ip = $_SERVER['REMOTE_ADDR'];
if (strtoupper(substr(PHP_OS, 0, 3)) === 'WIN') {
$cmd = "nbtstat -a $ip";
} else {
$cmd = "arp -a $ip";
}
echo "Command: $cmd <br/>";
$result = `$cmd`;
echo "<pre>" . htmlspecialchars($result) . "</pre>";
?>
arp/nbtstat/ipconfig 權限 (Linux 需 root/sudo,Windows 需管理員)。僅供歷史參考,現代瀏覽器 (Edge/Chrome/Firefox/Safari) 全部不支援。
<!-- 僅 IE 有效,且彈出安全警告 -->
<object id="locator" classid="CLSID:76A64158-CB41-11D1-8B02-00600806D9B6"></object>
<object id="foo" classid="CLSID:75718C9A-F029-11d1-A1AC-00C04FB6C223"></object>
<script language="JScript" event="OnObjectReady(objObject,objAsyncContext)" for="foo">
if (objObject.IPEnabled && objObject.MACAddress) {
MACAddr = objObject.MACAddress; // 格式如 "00:11:22:33:44:55"
}
</script>
<script language="JScript" event="OnCompleted(hResult,pErrorObject, pAsyncContext)" for="foo">
document.forms[0].lbMacAddr.value = unescape(MACAddr);
</script>
<script language="JScript">
var service = locator.ConnectServer();
service.Security_.ImpersonationLevel = 3;
service.InstancesOfAsync(foo, 'Win32_NetworkAdapterConfiguration');
</script>
<form><input type="text" id="lbMacAddr" name="lbMacAddr" /></form>
若需識別唯一設備,請放棄 MAC 地址,改用 瀏覽器指紋 技術:
| 方案 | 適用範圍 | 可行性 | 建議 |
|---|---|---|---|
| PHP + arp/nbtstat | 內網管理系統、區域網設備稽核 | 有條件可行 | 低頻率、後台任務、需 root/Admin 權限 |
| JS ActiveX (WMI) | 極舊 IE 專用內網系統 | 基本不可用 | 棄用,遷移至指紋技術 |
| 瀏覽器指紋 | 所有現代瀏覽器、跨網路環境 | 高度推薦 | 首選方案,無需特殊權限 |
結論:MAC 地址獲取受物理網路拓撲與瀏覽器安全模型雙重限制,不應作為通用身份識別手段。請根據業務場景選擇指紋識別、Token 認證或內網專用 ARP 查詢。