Come posso rilevare se l'utente è su localhost in PHP?


99

In altre parole, come posso sapere se la persona che utilizza la mia applicazione web si trova sul server su cui risiede? Se ricordo bene, PHPMyAdmin fa qualcosa di simile per motivi di sicurezza.

Risposte:


177

È inoltre possibile utilizzare $_SERVER['REMOTE_ADDR']per quale indirizzo IP del client richiedente è dato dal server web.

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

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

2
Il che renderebbe questo in realtà più facile da violare che falsificare l'IP. Dovresti davvero cambiarlo.
Pekka

3
@ skcin7 potrebbe essere l'impostazione del tuo server. controllalo.
mauris

4
@Pekka 웃 puoi semplicemente inviare ad esempio Host: 127.0.0.1e verrebbe popolato HTTP_HOST, quindi non è affatto un metodo affidabile.
Dejan Marjanović

4
Sì, questo è un pessimo consiglio e nella sua forma attuale e deve essere modificato o downvoted.
Pekka

3
Non dimenticare IPv6:$whitelist = array('127.0.0.1', '::1');
CrazyMax

26

Come complemento, come funzione ...

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

5
Come buona pratica, consiglierei di aggiungere "else return false;" in modo che la funzione restituisca sempre un valore booleano. In alternativa, rimuovi completamente "if" e invece "return in_array ($ _SERVER ['REMOTE_ADDR'], $ whitelist);"
Joe Irby

15

Gli utenti di sistemi operativi più recenti (Win 7, 8) potrebbero anche ritenere necessario includere un indirizzo remoto in formato IPV6 nel loro array whitelist:

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

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

14

$_SERVER["REMOTE_ADDR"]dovrebbe dirti l'IP dell'utente. Tuttavia è falsificabile.

Controlla questa domanda sulle taglie per una discussione molto dettagliata.

Penso che quello che ricordi con PHPMyAdmin sia qualcosa di diverso: molti server MySQL sono configurati in modo che sia possibile accedervi solo da localhost per motivi di sicurezza.


Vale la pena notare che alcuni server MySQL sono configurati in questo modo non legandosi a un'interfaccia pubblica. Allo stesso modo, se si desidera limitare un'applicazione PHP allo stesso modo, è necessario considerare di servirla tramite un'istanza di apache collegata solo a un'interfaccia interna.
Frank Farmer

8

Mi dispiace ma tutte queste risposte mi sembrano terribili. Suggerirei di riformulare la domanda perché in un certo senso tutte le macchine sono "localhost".

La domanda dovrebbe essere; Come eseguo percorsi di codice diversi a seconda della macchina su cui viene eseguito.

Secondo me, il modo più semplice è creare un file chiamato DEVMACHINE o quello che vuoi veramente e poi semplicemente controllare

file_exists ('DEVMACHINE')

Ricorda di escludere questo file durante il caricamento nell'ambiente di hosting live!

Questa soluzione non dipende dalla configurazione di rete, non può essere falsificata e semplifica il passaggio tra l'esecuzione di "codice live" e "codice di sviluppo".


6

Non sembra che dovresti usare $_SERVER['HTTP_HOST'], perché questo è il valore nell'intestazione http, facilmente falsificato.

Puoi usarlo $_SERVER["REMOTE_ADDR"]anche tu , questo è il valore più sicuro, ma è anche possibile fingere. Questo remote_addrè l'indirizzo a cui Apache restituisce il risultato.


REMOTE_ADDRè possibile fingere, tuttavia se vuoi fingere come 127.0.0.1o ::1, ciò richiede la compromissione della macchina, in cui uno spoofing REMOTE_ADDRè l'ultima delle tue preoccupazioni. Risposta pertinente - stackoverflow.com/a/5092951/3774582
Goose

1

Se vuoi avere una whitelist / allowlist che supporti IP statici e nomi dinamici .

Per esempio:

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

In questo modo potresti impostare un elenco di file nomi / IP che potranno (di sicuro) essere rilevati. I nomi dinamici aggiungono maggiore flessibilità per l'accesso da diversi punti.

Hai due opzioni comuni qui, puoi impostare un nome nel tuo file host locale o puoi semplicemente usare un provider di nomi dinamici che può essere trovato ovunque.

Questa funzione CACHES risulta perché gethostbyname è una funzione molto lenta.

Per questo puposo ho implementato questa funzione:

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

Per una migliore affidabilità potresti sostituire $ _SERVER ['REMOTE_ADDR'] con get_ip_address () che @Pekka ha menzionato nel suo post come "questa domanda di taglie"


1
Non so perché qualcuno abbia impostato un punteggio negativo alla mia risposta mentre offre chiaramente una risoluzione dei nomi dinamica e altri no. La risoluzione DNS è lenta, ecco perché sono necessarie le risoluzioni della cache.
Heroselohim

1

Che ne dici di confrontare $_SERVER['SERVER_ADDR'] === $_SERVER['REMOTE_ADDR']per determinare se il client è sulla stessa macchina del server?


$_SERVER['SERVER_ADDR']non sempre restituisce in modo affidabile l'indirizzo del server, ad esempio se si utilizzano i bilanciatori di carico restituisce l'indirizzo IP del bilanciatore di carico, credo.
Mike W

-2

Ho trovato una risposta facile.

Perché tutte le unità locali hanno C: o D: o F: ... ecc.

Rileva solo se il secondo carattere è un:

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';
}
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.