如何在PHP中获取连接客户端的MAC地址和IP地址?

157

我需要在PHP中获取连接客户端的MAC地址和IP地址,有什么方法可以做到这一点?


什么的IP地址?连接的客户端的IP地址吗? - Palantir
2
服务器地址还是访问者的地址? - KiNgMaR
14
您需要MAC地址的目的是什么?您是否知道用户可以更改MAC地址? - user207421
@EJP,我有一个使用MAC地址的用例。我想根据请求网页的设备提供不同的信息。是否有其他获取设备请求页面唯一信息的方法? - Dante
17个回答

207

服务器IP

您可以从$_SERVER['SERVER_ADDR']获取服务器IP地址。

服务器MAC地址

对于MAC地址,在Linux中,您可以解析netstat -ie的输出,在Windows中,您可以解析ipconfig /all的输出。

客户端IP地址

您可以从$_SERVER['REMOTE_ADDR']获取客户端IP地址。

客户端MAC地址

除非客户端和服务器在同一个以太网段上,否则您将无法获取客户端MAC地址。

因此,如果您正在构建基于局域网的系统,并且您的客户端在同一个以太网段上,那么您可以通过解析arp -n(Linux)或arp -a(Windows)的输出来获取MAC地址。

编辑:您在评论中提问如何获取外部命令的输出 – 一种方法是使用反引号,例如:

$ipAddress=$_SERVER['REMOTE_ADDR'];
$macAddr=false;

#run the external command, break output into lines
$arp=`arp -a $ipAddress`;
$lines=explode("\n", $arp);

#look for the output line describing our IP address
foreach($lines as $line)
{
   $cols=preg_split('/\s+/', trim($line));
   if ($cols[0]==$ipAddress)
   {
       $macAddr=$cols[1];
   }
}

但是如果客户端不在局域网上怎么办?

好吧,除非你能让客户端自愿提供这些信息并通过其他方式传输,否则你将没有任何运气。


3
如何使用 PHP 获取 arp -a 命令的输出? - Neveen
1
@paulDixon 你好,这是一篇旧帖子,我想知道是否有新的方法来获取Mac地址? - jcho360
7
个人建议采用IP地址+请求信息的组合,并对其进行哈希处理,例如md5($_SERVER['REMOTE_ADDR'] . $_SERVER['HTTP_USER_AGENT']);。这种方法并不是绝对可靠,但是可以作为一种起点。另一种更简单和安全的方法是使用带有唯一哈希值的cookie,在使用该cookie时,您可以确定连接到您网站的用户。 - Bearwulf
这总是返回与 $_SERVER['REMOTE_ADDR'] 完全相同的结果。 - SISYN
我没有看到你所提到的JavaScript建议。 - kasperd
显示剩余4条评论

25

每个路由器在客户端和服务器之间都会覆盖客户端(指发出HTTP请求的计算机)的MAC地址。

客户端IP可以方便地通过$_SERVER['REMOTE_ADDR']提供给脚本。在某些情况下,特别是当您的Web服务器位于代理(即缓存代理)后面时,$_SERVER['REMOTE ADDR']将返回代理的IP,并且通常会有一个额外的值$_SERVER['HTTP_X_FORWARDED_FOR'],其中包含原始请求客户端的IP。

有时,特别是当您正在处理无法控制的匿名代理时,代理将不返回真实的IP地址,而您所能得到的只是代理的IP地址。


9

对于Windows Server,我认为您可以使用以下方法:

<?php
echo exec('getmac');
?>

2
<?php echo exec('getmac'); ?> 这个只在局域网内工作,但是下面这个会显示所有的MAC地址 <php system('getmac'); ?> - Giorgi Gogitidze
还有Windows10。此外,您不必使用“exec”,只需使用“echo”“getmac”。 - SaidbakR

9

我认为在PHP中无法获取MAC地址,但是可以从$_SERVER['REMOTE_ADDR']变量中获取IP地址。


MAC地址仅对本地网络可见,您可以访问任何设备的MAC地址,例如您的MAC地址将存储并在本地WiFi路由器中可见,在其外部,所有网络中的设备都将使用相同的IP地址,并将与之通信,路由器将将其转换回MAC地址并将其发送到内部。 - Dheeraj Thedijje

7
你只需要将arp放入不同的组中即可。
默认值:
-rwxr-xr-x 1 root root 48K 2008-11-11 18:11 /usr/sbin/arp*

使用以下命令:

sudo chown root:www-data /usr/sbin/arp

你将获得:

-rwxr-xr-x 1 root www-data 48K 2008-11-11 18:11 /usr/sbin/arp*

因为Apache是在用户www-data下运行的守护进程,所以现在能够执行该命令。

因此,如果您现在使用一个PHP脚本,例如:

<?php
$mac = system('arp -an');
echo $mac;
?>

您将获得Linux arp -an命令的输出结果。


7
这只会给你本地网络设备的MAC地址。 - user149341
1
更改 arp 二进制文件的组是多余的,www-data 仍然从 other umode 中拥有执行权限。 - deed02392

1
在Windows系统中,如果用户本地使用您的脚本,那么非常简单:
<?php
// get all the informations about the client's network
 $ipconfig =   shell_exec ("ipconfig/all"));  
 // display those informations   
 echo $ipconfig;
/*  
  look for the value of "physical adress"  and use substr() function to 
  retrieve the adress from this long string.
  here in my case i'm using a french cmd.
  you can change the numbers according adress mac position in the string.
*/
 echo   substr(shell_exec ("ipconfig/all"),1821,18); 
?>

1

1
你可以使用这段代码获取MAC地址物理地址
$d = explode('Physical Address. . . . . . . . .',shell_exec ("ipconfig/all"));  
$d1 = explode(':',$d[1]);  
$d2 = explode(' ',$d1[1]);  
return $d2[1];

我多次使用explode函数,因为shell_exec("ipconfig/all")返回所有网络的完整细节,所以你需要一个一个地拆分。 当你运行这段代码时,你将获得: 你的MAC地址00-##-##-CV-12 //这只是展示用的虚假地址。

1

回答晚了,但这是我的方法,因为没有人在这里提到:
为什么不采用客户端解决方案?
使用JavaScript实现将MAC地址存储在Cookie中(您可以在此之前对其进行加密)
然后每个请求都必须包含该Cookie名称,否则它将被拒绝。
为了使这更有趣,您可以进行服务器端验证
从MAC地址中获取制造商(有很多免费的API可用于此)
然后将其与user_agent值进行比较,以查看是否存在某种操作:
HP的MAC地址+ Safari的用户代理=拒绝请求。


1
我喜欢基于JavaScript的解决方案的想法。你能提供一个代码示例吗?我在搜索中看到的大多数内容都说不行。 - Ifedi Okonkwo

0
您可以使用以下解决方案来解决您的问题:
$mac='UNKNOWN';
foreach(explode("\n",str_replace(' ','',trim(`getmac`,"\n"))) as $i)
if(strpos($i,'Tcpip')>-1){$mac=substr($i,0,17);break;}
echo $mac;

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接