Как я могу определить, находится ли пользователь на локальном хосте в PHP?


99

Другими словами, как я могу узнать, находится ли человек, использующий мое веб-приложение, на сервере, на котором оно находится? Если я правильно помню, PHPMyAdmin делает что-то подобное из соображений безопасности.

Ответы:


177

Вы также можете указать, $_SERVER['REMOTE_ADDR']какой IP-адрес запрашиваемого клиента предоставлен веб-сервером.

$whitelist = array(
    '127.0.0.1',
    '::1'
);

if(!in_array($_SERVER['REMOTE_ADDR'], $whitelist)){
    // not valid
}

2
Это сделало бы его проще взломать, чем спуфинг IP. Тебе действительно стоит это изменить.
Pekka

3
@ skcin7 может быть настройкой вашего сервера. Проверь это.
mauris

4
@Pekka 웃 вы можете просто отправить, например, Host: 127.0.0.1и он будет заполнен HTTP_HOST, так что это вообще ненадежный метод.
Деян Марьянович

4
Да, это плохой совет, и в его нынешней форме его нужно отредактировать или проголосовать против.
Pekka

3
Не забывайте IPv6:$whitelist = array('127.0.0.1', '::1');
CrazyMax

26

Как дополнение, как функция ...

function isLocalhost($whitelist = ['127.0.0.1', '::1']) {
    return in_array($_SERVER['REMOTE_ADDR'], $whitelist);
}

5
В качестве хорошей практики я бы рекомендовал добавить «else return false;» так что функция всегда возвращает логическое значение. Или, наоборот, просто удалите «if» полностью и вместо этого «return in_array ($ _SERVER ['REMOTE_ADDR'], $ whitelist);»
Джо Ирби

15

Новые пользователи ОС (Win 7, 8) также могут счесть необходимым включить удаленный адрес в формате IPV6 в свой массив белого списка:

$whitelist = array('127.0.0.1', "::1");

if(!in_array($_SERVER['REMOTE_ADDR'], $whitelist)){
    // not valid
}

14

$_SERVER["REMOTE_ADDR"]должен сообщить вам IP-адрес пользователя. Хотя это подделка.

Отметьте этот вопрос о вознаграждении для очень подробного обсуждения.

Я думаю, что то, что вы помните, с PHPMyAdmin - это нечто иное: многие серверы MySQL настроены так, что к ним можно получить доступ только с localhost из соображений безопасности.


Стоит отметить, что некоторые серверы MySQL настроены таким образом, что не привязаны к общедоступному интерфейсу. Точно так же, если вы хотите таким же образом ограничить приложение PHP, вам следует рассмотреть возможность обслуживания его через экземпляр apache, привязанный только к внутреннему интерфейсу.
Фрэнк Фармер,

8

Извините, но все эти ответы кажутся мне ужасными. Я бы предложил перефразировать вопрос, потому что в некотором смысле все машины являются "локальными".

Вопрос должен быть; Как запустить разные пути кода в зависимости от того, на каком компьютере он выполняется.

На мой взгляд, самый простой способ - создать файл с именем DEVMACHINE или что угодно, а затем просто проверить

file_exists ('DEVMACHINE')

Не забудьте исключить этот файл при загрузке в среду живого хостинга!

Это решение не зависит от конфигурации сети, его нельзя подделать, и оно позволяет легко переключаться между запущенным «live-code» и «dev-code».


6

Не похоже, что вам следует использовать $_SERVER['HTTP_HOST'], потому что это значение в заголовке http, которое легко подделать.

Вы $_SERVER["REMOTE_ADDR"]тоже можете использовать , это более безопасное значение, но также можно подделать. Это remote_addrадрес, по которому Apache возвращает результат.


REMOTE_ADDRможно подделать, однако, если вы хотите подделать его как 127.0.0.1или ::1, что требует компрометации машины, в которой подделка - меньшая REMOTE_ADDRиз ваших проблем. Соответствующий ответ - stackoverflow.com/a/5092951/3774582
Гусь,

1

Если вы хотите иметь белый список / список разрешений, который поддерживает статические IP-адреса и динамические имена .

Например:

$whitelist = array("localhost", "127.0.0.1", "devel-pc.ds.com", "liveserver.com");
if (!isIPWhitelisted($whitelist)) die();

Таким образом, вы можете установить список имен / IP-адресов, которые будут (наверняка) обнаружены. Динамические имена добавляют больше гибкости для доступа из разных точек.

У вас есть два общих варианта: вы можете указать имя в файле локальных хостов или просто использовать один поставщика динамических имен. который можно найти где угодно.

Эта функция КЭШЕТ результаты, потому что gethostbyname - очень медленная функция.

Для этой цели я реализовал эту функцию:

function isIPWhitelisted($whitelist = false)
{
    if ( isset($_SESSION) && isset($_SESSION['isipallowed']) )
        { return $_SESSION['isipallowed'];  }

    // This is the whitelist
    $ipchecklist = array("localhost", "127.0.0.1", "::1");
    if ($whitelist) $ipchecklist = $whitelist;

    $iplist = false;
    $isipallowed = false;

    $filename = "resolved-ip-list.txt";
    $filename = substr(md5($filename), 0, 8)."_".$filename; // Just a spoon of security or just remove this line

    if (file_exists($filename))
    {
        // If cache file has less than 1 day old use it
        if (time() - filemtime($filename) <= 60*60*24*1)
            $iplist = explode(";", file_get_contents($filename)); // Read cached resolved ips
    }

    // If file was not loaded or found -> generate ip list
    if (!$iplist)
    {
        $iplist = array(); $c=0;
        foreach ( $ipchecklist as $k => $iptoresolve )
        {
            // gethostbyname: It's a VERY SLOW function. We really need to cache the resolved ip list
            $ip = gethostbyname($iptoresolve);
            if ($ip != "") $iplist[$c] = $ip;
            $c++;
        }

        file_put_contents($filename, implode(";", $iplist));
    }

    if (in_array($_SERVER['REMOTE_ADDR'], $iplist)) // Check if the client ip is allowed
        $isipallowed = true;

    if (isset($_SESSION)) $_SESSION['isipallowed'] = $isipallowed;

    return $isipallowed;
}

Для большей надежности вы можете заменить $ _SERVER ['REMOTE_ADDR'] на get_ip_address (), который @Pekka упомянул в своем сообщении как «этот вопрос о награде».


1
Я не знаю, почему кто-то поставил отрицательную оценку моему ответу, хотя он явно предлагает динамическое разрешение имен, а другие нет. Разрешение DNS медленное, поэтому требуется разрешение кеширования.
Heroselohim

1

Как насчет сравнения, $_SERVER['SERVER_ADDR'] === $_SERVER['REMOTE_ADDR']чтобы определить, находится ли клиент на той же машине, что и сервер?


$_SERVER['SERVER_ADDR']не всегда надежно возвращает адрес сервера, например, при использовании балансировщиков нагрузки он возвращает IP-адрес балансировщика нагрузки, как я полагаю.
Mike W

-2

Я нашел простой ответ.

Потому что на всех локальных дисках есть C: или D: или F: ... и т. Д.

Просто определите, является ли второй символ:

if ( substr_compare(getcwd(),":",1,1) == 0)
{
echo '<script type="text/javascript">alert(" The working dir is at the local computer ")</script>';
    $client_or_server = 'client';
}
else
{
echo '<script type="text/javascript">alert(" The working dir is at the server ")</script>';
    $client_or_server = 'server';
}
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.