Fitur PHP : Autentikasi HTTP dengan PHP

Oleh : Abah Razi

بسم الله الرحمن الرحيم

Adalah dimungkinkan untuk menggunakan fungsi header untuk mengirimkan suatu pesan “Authentication Required” ke browser klien yang memunculkan popup input username/password. Setelah pengguna mengisi username dan password, URL yang berisi script PHP akan dipanggil lagi dengan serangkaian predefined variable PHP_AUTH_USER,PHP_AUTH_PW dan AUTH_TYPE untuk username, password dan tipe autentikasi. Variabel-variabel predefined ini didapati di array $_SERVER dan <code?$HTTP_SERVER_VARS. Baik metode autentikasi “Basic” maupun “Digest” keduanya didukung (semenjak PHP 5.1.0). Lihat fungsi header() untuk informasi lebih lanjut.

Catatan Versi PHP
Superglobal, seperti $_SERVER ada semenjak PHP 4.1.0

Berikut contoh potongan scrip yang dapat memaksa autentikasi klien di halaman :


<?php
if (!isset($_SERVER['PHP_AUTH_USER'])) {
    header('WWW-Authenticate: Basic realm="My Realm"');
    header('HTTP/1.0 401 Unauthorized');
    echo 'Text to send if user hits Cancel button';
    exit;
} else {
    echo "<p>Hello {$_SERVER['PHP_AUTH_USER']}.</p>";
    echo "<p>You entered {$_SERVER['PHP_AUTH_PW']} as your password.</p>";
}
?>

Contoh 2 : Contoh Autentikasi HTTP Digest

Contoh berikut menunjukkan bagaimana mengimplementasikan script autentikasi HTTP Digest sederhana. Untuk informasi lebih lengkap silahkan rujuk RFC 2617


<?php
$realm = 'Restricted area';

//user => password
$users = array('admin' => 'mypass', 'guest' => 'guest');


if (empty($_SERVER['PHP_AUTH_DIGEST'])) {
    header('HTTP/1.1 401 Unauthorized');
    header('WWW-Authenticate: Digest realm="'.$realm.
           '",qop="auth",nonce="'.uniqid().'",opaque="'.md5($realm).'"');

    die('Text to send if user hits Cancel button');
}


// analyze the PHP_AUTH_DIGEST variable
if (!($data = http_digest_parse($_SERVER['PHP_AUTH_DIGEST'])) ||
    !isset($users[$data['username']]))
    die('Wrong Credentials!');


// generate the valid response
$A1 = md5($data['username'] . ':' . $realm . ':' . $users[$data['username']]);
$A2 = md5($_SERVER['REQUEST_METHOD'].':'.$data['uri']);
$valid_response = md5($A1.':'.$data['nonce'].':'.$data['nc'].':'.$data['cnonce'].':'.$data['qop'].':'.$A2);

if ($data['response'] != $valid_response)
    die('Wrong Credentials!');

// ok, valid username & password
echo 'You are logged in as: ' . $data['username'];


// function to parse the http auth header
function http_digest_parse($txt)
{
    // protect against missing data
    $needed_parts = array('nonce'=>1, 'nc'=>1, 'cnonce'=>1, 'qop'=>1, 'username'=>1, 'uri'=>1, 'response'=>1);
    $data = array();
    $keys = implode('|', array_keys($needed_parts));

    preg_match_all('@(' . $keys . ')=(?:([\'"])([^\2]+?)\2|([^\s,]+))@', $txt, $matches, PREG_SET_ORDER);

    foreach ($matches as $m) {
        $data[$m[1]] = $m[3] ? $m[3] : $m[4];
        unset($needed_parts[$m[1]]);
    }

    return $needed_parts ? false : $data;
}
?>

Catatan Kompatibilitas :
Berhati-hatilah saat mengkoding baris header HTTP. Untuk menjamin kompatibilitas maksimum ke seluruh klien, kata kunci “Basic” seharusnya diketik dengan huruf besar “B”, string realm mesti ditutup dengan tanda petik dua (bukan satu), dan hanya boleh ada satu spasi pada kode 401 di bari header HTTP/1.0 401. Parameter-parameter autentikasi mestilah dipisahkan dengan koma seperti yang terlihat pada contoh diatas.

Alih-alih secara sederhana mengetikkan PHP_AUTH_USER dan PHP_AUTH_PW sebagaimana yang kita lakukan diatas, kita dapat juga mengecek username dan password untuk validitas. Misalnya dengan mengirimkan query ke database, atau dengan mengecek pengguna di sebuah file dbm.

Awas pula dengan buggy di Internet Explorer. Dia tampak sangat pilih-pilih terkait urutan header. Mengirimkan header WWW-Authenticate sebelum header HTTP/1.0 401 tampaknya dapat digunakan sebagai trik saat ini

Semenjak PHP 4.3.0, dalam rangka mencegah seseorang menulis suatu script yang dapat menemukan password sebuah halaman yang diautentikasi melalui mekanisme eksternal tradisional, variabel-variabel PHP_AUTH tidak akan diset jika autentikasi eksternal diaktifkan untuk halaman tertentu dan safe mode dipasang. Bagaimanapun, REMOTE_USER dapat digunakan untuk mengidentifikasi user yang diautentikasi secara eksternal, jadi kita dapat menggunakan $_SERVER['REMOTE_USER'].

Catatan Konfigurasi
PHP menggunakan suatu direktif AuthType untuk menentukan apakah autentikasi eksternal memberikan efek.
Perhatikan, bagaimapun, hal itu tidak mencegah seseorang yang mengendalikan suatu URL non-authenticated untuk mencuri password dari URL terautentikasi pada server yang sama.

Baik Netscape Navigator maupun Internet Explorer akan membersihkan jendela cache autentikasi browser lokal untuk realm saat menerima respon server 401. Hal ini dapat secara efektif me”log-out” pengguna, memaksa mereka untuk mengisikan ulang username dan password. Beberapa orang menggunakan ini untuk login “time out”, atau untuk menyediakan tombol “log-out”.

Contoh 3 Contoh Autentikasi HTTP memaksa sebuah nama/password baru


<?php
function authenticate() {
    header('WWW-Authenticate: Basic realm="Test Authentication System"');
    header('HTTP/1.0 401 Unauthorized');
    echo "You must enter a valid login ID and password to access this resource\n";
    exit;
}
 
if (!isset($_SERVER['PHP_AUTH_USER']) ||
    ($_POST['SeenBefore'] == 1 && $_POST['OldAuth'] == $_SERVER['PHP_AUTH_USER'])) {
    authenticate();
} else {
    echo "<p>Welcome: " . htmlspecialchars($_SERVER['PHP_AUTH_USER']) . "<br />";
    echo "Old: " . htmlspecialchars($_REQUEST['OldAuth']);
    echo "<form action='' method='post'>\n";
    echo "<input type='hidden' name='SeenBefore' value='1' />\n";
    echo "<input type='hidden' name='OldAuth' value=\"" . htmlspecialchars($_SERVER['PHP_AUTH_USER']) . "\" />\n";
    echo "<input type='submit' value='Re Authenticate' />\n";
    echo "</form></p>\n";
}
?>

Prilaku ini tidak dibutuhkan oleh standar autentikasi HTTP Basic, jadi kita seharusnya tidak pernah bergantung pada hal ini. Pengujian dengan Lynx telah menunjukkan bahwa Lynx tidak membersihkan kredensial autentikasi dengan respon server 401, sehingga menekan tombol “kembali” akan membukan kembali resource tersebut sepanjang kebutuhan kredensial tidak berubah. Pengguna dapat menekan tombol ‘_’ untuk membersihkan informasi autentikasi mereka.

Catat juga bahwa hingga PHP 4.3.3, autentikasi HTTP tidak bekerja menggunakan server IIS Microsoft dengan versi CGI PHP dikarenakan pembatasan di IIS. Untuk dapat membuatnya bekerja pada PHP 4.3.3+, kita mesti mengedit konfigurasi IIS “Directory Security”. Klik pada tombol “Edit” dan cukup berikan tanda pada “Anonymous Access”, sementara field yang lain sebaiknya dibiarkan tidak dicentang.

Limitasi yang lain adalah jika kita menggunakan modul IIS (ISAPI) dan PHP 4, kita tidak dapat menggunakan variabel PHP_AUTH_* tetapi dapat menggunakan variabel HTTP_AUTHORIZATION. Sebagai contoh perhatikan kode berikut


list($user, $pw) = explode(':', base64_decode(substr($_SERVER['HTTP_AUTHORIZATION'], 6)));

Catatan IIS
Agar autentikasi HTTP bekerja di IIS, direktif PHP headercgi.rfc2616_headers mesti diset bernilai 0 (nilai default)

Catatan
Jika safe mode diaktifkan, uid dari script ditambahkan ke bagian realm di header WWW-Authenticate

About Reza Ervani 426 Articles
Adalah pendiri programming.rezaervani.com -

Be the first to comment

Leave a Reply

Your email address will not be published.


*


This site uses Akismet to reduce spam. Learn how your comment data is processed.