PHP: как проверить, является ли клиент локальным?


Мне нужно проверить, открыт ли файл "локально" (на той же машине или в сети). Я использую:

<?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
}

Но я не уверен, что это лучший способ.

Какой более надежный способ сделать это?

Author: Pacerier, 2011-08-09

3 answers

"Защита от дурака", как всегда, может быть сложной.

Если мы ограничимся IPv4, то проверка на "127.0.0.1" позаботится о случае локального хоста, но проверка на "192.168." явно неверна - это будет работать только в том случае, если скрипт запускается на сервере, который находится в сети 192.168, используя 16-разрядную маску подсети.

Проверка $_SERVER['REMOTE_ADDR'] против $_SERVER['SERVER_ADDR'] была бы лучшей ставкой. Это все еще не касается случая с многоквартирным домом хост (т. Е. тот, у которого есть несколько IP-адресов в дополнение к 127.0.0.1), хотя.

Чтобы перехватить все случаи с одной и той же сетью, вам нужно будет проверить комбинацию SERVER_ADDR и маски подсети на соответствие REMOTE_ADDR, но маска подсети недоступна в $_SERVER.

НО я нашел функцию, которая делает в значительной степени то, что вы хотите здесь. Это на пару экранов ниже, и это называется clientInSameSubnet. Не мой код, но выглядит правильно.

 10
Author: Uffe, 2011-08-28 20:12:58

То, что сказал Фрик, верно, но при условии, что вы знаете, как получить IP-адрес реального клиента, вы можете определить, является ли он локальным адресом, используя фильтры PHP:

if ( ! filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_NO_PRIV_RANGE | FILTER_FLAG_NO_RES_RANGE) )
{
    // is a local ip address
}
 43
Author: Miguel Trias, 2017-10-07 13:20:05

На случай, если у кого-то возникнут проблемы с поиском вышеуказанного кода, предложенного @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:(\d{1,3}\.\d{1,3}i\.\d{1,3}\.\d{1,3}).*";
    $match .= "Mask:(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,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));
}
 3
Author: Troy Alford, 2015-11-16 00:13:51