Bagaimana saya bisa mendeteksi jika pengguna menggunakan localhost di PHP?

99

Dengan kata lain, bagaimana saya bisa mengetahui jika orang yang menggunakan aplikasi web saya ada di server tempatnya berada? Jika saya ingat dengan benar, PHPMyAdmin melakukan sesuatu seperti ini untuk alasan keamanan.

Richie Marquez
sumber

Jawaban:

177

Anda juga dapat menggunakan $_SERVER['REMOTE_ADDR']alamat IP mana yang diminta klien diberikan oleh server web.

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

if(!in_array($_SERVER['REMOTE_ADDR'], $whitelist)){
    // not valid
}
mauris
sumber
2
Yang akan membuat ini lebih mudah untuk dipecahkan daripada memalsukan IP. Anda benar-benar harus mengubahnya.
Pekka
3
@ skcin7 mungkin adalah pengaturan server Anda. Periksa.
mauris
4
@Pekka 웃 Anda bisa mengirim misalnya Host: 127.0.0.1dan itu akan diisi HTTP_HOST, jadi itu bukan metode yang dapat diandalkan sama sekali.
Dejan Marjanović
4
Ya, ini adalah nasihat yang buruk dan dalam bentuknya saat ini dan perlu diedit - atau diberi suara negatif.
Pekka
3
Jangan lupa IPv6:$whitelist = array('127.0.0.1', '::1');
CrazyMax
26

Sebagai pelengkap, sebagai fungsi ...

function isLocalhost($whitelist = ['127.0.0.1', '::1']) {
    return in_array($_SERVER['REMOTE_ADDR'], $whitelist);
}
Jens Törnell
sumber
5
Sebagai praktik yang baik, saya akan merekomendasikan menambahkan "else return false;" sehingga fungsi tersebut selalu mengembalikan nilai boolean. Atau sebagai gantinya, hapus saja "if" sepenuhnya dan sebagai gantinya "return in_array ($ _SERVER ['REMOTE_ADDR'], $ whitelist);"
Joe Irby
15

Pengguna OS yang lebih baru (Win 7, 8) mungkin juga merasa perlu untuk menyertakan alamat jarak jauh format IPV6 dalam susunan daftar putih mereka:

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

if(!in_array($_SERVER['REMOTE_ADDR'], $whitelist)){
    // not valid
}
rgdigital.dll
sumber
14

$_SERVER["REMOTE_ADDR"]harus memberi tahu Anda IP pengguna. Tapi itu spoofable.

Periksa pertanyaan karunia ini untuk pembahasan yang sangat rinci.

Saya pikir apa yang Anda ingat dengan PHPMyAdmin adalah sesuatu yang berbeda: Banyak Server MySQL dikonfigurasi sehingga hanya dapat diakses dari localhost untuk alasan keamanan.

Pekka
sumber
Perlu dicatat bahwa beberapa server MySQL sangat dikonfigurasi dengan tidak mengikat ke antarmuka publik. Demikian pula, jika Anda ingin membatasi aplikasi PHP dengan cara yang sama, Anda harus mempertimbangkan untuk menyajikannya melalui instance apache yang hanya terikat ke antarmuka internal.
Frank Farmer
8

Maaf, tetapi semua jawaban ini tampak mengerikan bagi saya. Saya menyarankan untuk mengulang pertanyaan karena dalam arti semua mesin adalah "localhost".

Pertanyaannya seharusnya; Bagaimana cara menjalankan jalur kode yang berbeda tergantung pada mesin mana ia dijalankan.

Menurut saya, cara termudah adalah dengan membuat file bernama DEVMACHINE atau apa pun yang Anda inginkan sebenarnya dan kemudian cukup centang

file_exists ('DEVMACHINE')

Ingatlah untuk mengecualikan file ini saat mengupload ke lingkungan hosting langsung!

Solusi ini tidak bergantung pada konfigurasi jaringan, tidak dapat dipalsukan dan memudahkan peralihan antara menjalankan "live-code" dan "dev-code".

Daniklad
sumber
6

Tampaknya Anda tidak perlu menggunakan $_SERVER['HTTP_HOST'], karena ini adalah nilai di header http, mudah dipalsukan.

Anda dapat menggunakan $_SERVER["REMOTE_ADDR"]juga, ini adalah nilai yang lebih aman, tetapi juga dapat dipalsukan. Ini remote_addradalah alamat di mana Apache mengembalikan hasil.

nicola
sumber
REMOTE_ADDRadalah mungkin untuk memalsukan, namun jika Anda ingin memalsukannya sebagai 127.0.0.1atau ::1, yang memerlukan kompromi mesin, di mana yang palsu REMOTE_ADDRadalah kekhawatiran Anda yang paling kecil. Jawaban yang relevan - stackoverflow.com/a/5092951/3774582
Angsa
1

Jika Anda ingin memiliki whitelist / allowlist yang mendukung IP statis dan nama dinamis .

Sebagai contoh:

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

Dengan cara ini Anda dapat mengatur daftar nama / IP yang akan (pasti) dapat dideteksi. Nama dinamis menambah lebih banyak fleksibilitas untuk mengakses dari berbagai titik.

Anda memiliki dua opsi umum di sini, Anda dapat menetapkan nama di file host lokal Anda atau Anda dapat menggunakan satu penyedia nama dinamis yang dapat ditemukan di mana saja.

Fungsi ini CACHES dihasilkan karena gethostbyname adalah fungsi yang sangat lambat.

Untuk pupose ini saya telah menerapkan fungsi ini:

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

Untuk keandalan yang lebih baik, Anda dapat mengganti $ _SERVER ['REMOTE_ADDR'] untuk get_ip_address () yang disebutkan @Pekka di posnya sebagai "pertanyaan hadiah ini"

Heroselohim
sumber
1
Saya tidak tahu mengapa seseorang memberikan skor negatif pada jawaban saya sementara itu dengan jelas menawarkan resolusi nama yang dinamis dan yang lainnya tidak. Resolusi DNS lambat, itulah mengapa resolusi cache diperlukan.
Heroselohim
1

Bagaimana jika membandingkan $_SERVER['SERVER_ADDR'] === $_SERVER['REMOTE_ADDR']untuk menentukan apakah klien menggunakan mesin yang sama dengan server?

Eugen Wesseloh
sumber
$_SERVER['SERVER_ADDR']tidak selalu dapat mengembalikan alamat server dengan andal, misalnya jika menggunakan penyeimbang beban, ia mengembalikan alamat IP penyeimbang beban yang saya yakini.
Mike W
-2

Saya menemukan jawaban yang mudah.

Karena semua drive lokal memiliki C: atau D: atau F: ... dll.

Deteksi saja apakah karakter kedua adalah:

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';
}
Scoobeedo Cool
sumber