PHP:如何检查客户端是不是是本地的?

Posted

技术标签:

【中文标题】PHP:如何检查客户端是不是是本地的?【英文标题】:PHP: how to check if the client is local?PHP:如何检查客户端是否是本地的? 【发布时间】:2011-10-23 08:56:40 【问题描述】:

我需要检查文件是否在“本地”(同一台机器或网络)打开。我正在使用:

<?php
if ((substr($_SERVER['REMOTE_ADDR'],0,8) == "192.168.") || ($_SERVER['REMOTE_ADDR'] == "127.0.0.1")) 
    // client is local
 else 
    // client is not local

但我不确定这是不是最好的方法。

有什么更简单的方法?

【问题讨论】:

在这里您将自己限制为 IPv4。如今,这还不够。您应该 a) 也熟悉 IPv6,并且 b) 定义定义列表什么是“本地”:真的只有 192.168.*?如果您在具有自己 IP 的网络中怎么办?还是在 10.* 网络内? How to know if an IP is external or not? 的可能重复项 【参考方案1】:

Friek 说的是真的,但前提是你知道如何获取真实客户端的 IP,你可以使用 PHP filters 判断它是否是本地地址:

if ( ! filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_NO_PRIV_RANGE | FILTER_FLAG_NO_RES_RANGE) )

    // is a local ip address

【讨论】:

如果真正的客户端 IP 是 IPv6,这将不起作用。 它应该根据 2010 年的这个问题工作:bugs.php.net/bug.php?id=47435【参考方案2】:

“万无一失”,一如既往,可能很棘手。

如果我们确实限制自己使用 IPv4,则检查“127.0.0.1”会处理 localhost 的情况,但会检查“192.168”。完全错误 - 只有在恰好位于 192.168 网络的服务器上运行脚本时,它才会使用 16 位子网掩码。

对照 $_SERVER['SERVER_ADDR'] 检查 $_SERVER['REMOTE_ADDR'] 会是更好的选择。不过,这仍然不能解决多宿主主机(即除了 127.0.0.1 之外还有多个 IP 地址的主机)的情况。

为了捕获所有相同网络的情况,您需要根据 REMOTE_ADDR 检查 SERVER_ADDR 和子网掩码的组合,但子网掩码在 $_SERVER 中不可用。

但是我找到了一个功能,它几乎可以满足您的需求here。这是几个屏幕,它被称为clientInSameSubnet。不是我的代码,但看起来不错。

【讨论】:

检查 $_SERVER['SERVER_ADDR'] 是个坏主意。在 rfc1918 空间中拥有虚拟主机并不一定意味着客户端也来自该空间。例如,有负载均衡结构,其中节点位于私有子网中,而负载均衡器具有“公共”IP(请参阅linuxvirtualserver.org/VS-NAT.html 你肯定有一个观点,正如我所说,万无一失并不容易。但是比问题中引用的代码要好,而且涵盖了常见的情况。 @Uffe, 那么我们如何从 PHP 中获取与子网掩码相关的信息呢? 尝试使用客户端 IP=192.168.10.10 和服务器 IP=192.168.10.1 运行 clientInSameSubnet() 函数,它返回 false。我是否误解了该功能的作用?好像应该是真的……【参考方案3】:

如果有人无法找到@Uffe 建议的上述代码,我将其包含在下面:

<?php
/**
* Check if a client IP is in our Server subnet
*
* @param string $client_ip
* @param string $server_ip
* @return boolean
*/
function clientInSameSubnet($client_ip=false,$server_ip=false) 
    if (!$client_ip)
        $client_ip = $_SERVER['REMOTE_ADDR'];
    if (!$server_ip)
        $server_ip = $_SERVER['SERVER_ADDR'];

    // Extract broadcast and netmask from ifconfig
    if (!($p = popen("ifconfig","r"))) return false;
    $out = "";
    while(!feof($p))
        $out .= fread($p,1024);
    fclose($p);

    // This is to avoid wrapping.
    $match  = "/^.*".$server_ip;
    $match .= ".*Bcast:(\d1,3\.\d1,3i\.\d1,3\.\d1,3).*";
    $match .= "Mask:(\d1,3\.\d1,3\.\d1,3\.\d1,3)$/im";
    if (!preg_match($match,$out,$regs))
        return false;

    $bcast = ip2long($regs[1]);
    $smask = ip2long($regs[2]);
    $ipadr = ip2long($client_ip);
    $nmask = $bcast & $smask;

    return (($ipadr & $smask) == ($nmask & $smask));

【讨论】:

以上是关于PHP:如何检查客户端是不是是本地的?的主要内容,如果未能解决你的问题,请参考以下文章

如何检查 Windows 文件是不是可读/可写?

如何在使用本地 CRL 文件(C#)的验证过程中检查客户端证书吊销

如何检查Google客户端API密钥是否对Google PHP API库有效?

检查文件在php中是不是存在正则表达式[重复]

如何检查远程 Oracle 服务器是不是已启动并正在运行

如何使用php获取客户端的本地IP?