Як я можу виявити, чи користувач перебуває на localhost в 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 налаштовані так, що до них можна отримати доступ лише з локального хосту з міркувань безпеки.


Варто відзначити, що деякі сервери MySQL настільки налаштовані, не прив’язуючись до загальнодоступного інтерфейсу. Аналогічно, якщо ви хотіли таким же чином обмежити додаток PHP, вам слід розглянути можливість його обслуговування через екземпляр apache, прив'язаний лише до внутрішнього інтерфейсу.
Френк Фермер

8

Вибачте, але всі ці відповіді мені здаються жахливими. Я б запропонував перефразувати питання, оскільки в певному сенсі всі машини є "локальним хостом".

Питання має бути; Як запускати різні кодові контури залежно від того, на якій машині він виконаний.

На мою думку, найпростіший спосіб - створити файл під назвою DEVMACHINE або все, що ви хочете насправді, а потім просто перевірити

file_exists ("DEVMACHINE")

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

Це рішення не залежить від конфігурації мережі, не може бути підроблено і полегшує перемикання між запущеними "live-кодом" та "dev-кодом".


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-адрес, які зможуть (точно) виявити. Динамічні імена додають більшої гнучкості для доступу з різних точок.

Тут у вас є два загальні варіанти, ви можете встановити ім’я у вашому локальному файлі хостів або ви можете просто скористатися одним динамічним постачальником імен, який можна знайти де завгодно.

Ця функція CACHES дає результат, оскільки 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 повільний, тому потрібні роздільні можливості кешування.
Героселохім

1

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


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

-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.