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
}
Но я не уверен, что это лучший способ.
Какой более надежный способ сделать это?
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. Не мой код, но выглядит правильно.
То, что сказал Фрик, верно, но при условии, что вы знаете, как получить IP-адрес реального клиента, вы можете определить, является ли он локальным адресом, используя фильтры PHP:
if ( ! filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_NO_PRIV_RANGE | FILTER_FLAG_NO_RES_RANGE) )
{
// is a local ip address
}
На случай, если у кого-то возникнут проблемы с поиском вышеуказанного кода, предложенного @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));
}