Forum und email

Autenticazione HTTP usando PHP

I meccanismi di Autenticazione HTTP sono disponibili in PHP solo quando questo viene usato come un modulo di Apache ed esso non è quindi disponibile nella versione CGI. In uno script PHP modulo di Apache, è possibile usare la funzione header() per inviare un messaggio di "Authentication Required" al browser dell'utente, provocando quindi l'apertura di una finestra contenente una richiesta di Nome utente/Password. Una volta che l'utente ha compilato i campi nome utente e password, l'URL contenente lo script PHP verrà richiamato nuovamente usando le variabili predefinite, PHP_AUTH_USER, PHP_AUTH_PW e AUTH_TYPE impostate con, rispettivamente: nome, password e tipo di autenticazione. Queste variabili predefinite possono essere trovate negli array $_SERVER e $HTTP_SERVER_VARS. Saranno supportati entrambi i metodi di autenticazione, "Basic" e "Digest" (a partire dal PHP 5.1.0). Fare riferimento alla funzione header() per ulteriori informazioni.

Nota: Nota sulla versione di PHP Le variabili autoglobali, come $_SERVER, esistono a partire da PHP » 4.1.0. $HTTP_SERVER_VARS è disponibile a partire da PHP 3.

Un frammento di script di esempio che richiede l'autenticazione da parte del browser su una pagina, potrebbe essere il seguente:

Example#1 Esempio di Autenticazione HTTP "Basic"

<?php
  
if (!isset($_SERVER['PHP_AUTH_USER'])) {
    
header('WWW-Authenticate: Basic realm="Il mio realm"');
    
header('HTTP/1.0 401 Unauthorized');
    echo 
'Messaggio da inviare se si preme il tasto Cancel';
    exit;
  } else {
    echo 
"<p>Ciao {$_SERVER['PHP_AUTH_USER']}.</p>";
    echo 
"<p>Hai inserito {$_SERVER['PHP_AUTH_PW']} come tua password.</p>";
  }
?>

Example#2 Esempio di autenticazione HTTP "Digest"

Questo esempio illustra come implementare una autenticazione Digest. Per maggiori dettagli vedere » RFC 2617.

<?php
$realm 
'Restricted area';
 
//user => password
$users = array('admin' => 'mypass''guest' => 'guest');
 
 
if (!isset(
$_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');
}
 
// analisi della variabile PHP_AUTH_DIGEST
preg_match('/username="(?P<username>.*)",\s*realm="(?P<realm>.*)",\s*nonce="(?P<nonce>.*)",\s*uri="(?P<uri>.*)",\s*response="(?P<response>.*)",\s*opaque="(?P<opaque>.*)",\s*qop=(?P<qop>.*),\s*nc=(?P<nc>.*),\s*cnonce="(?P<cnonce>.*)"/'$_SERVER['PHP_AUTH_DIGEST'], $digest);
 
if (!isset(
$users[$digest['username']]))
    die(
'Username not valid!');
 
 
// generazione di una risposta valida
$A1 md5($digest['username'] . ':' $realm ':' $users[$digest['username']]);
$A2 md5($_SERVER['REQUEST_METHOD'].':'.$digest['uri']);
$valid_response md5($A1.':'.$digest['nonce'].':'.$digest['nc'].':'.$digest['cnonce'].':'.$digest['qop'].':'.$A2);
 
if (
$digest['response'] != $valid_response)
    die(
'Wrong Credentials!');
 
// Ok, utente/passworrd validi
echo 'Your are logged in as: ' $digest['username'];
       
?>

Nota: Note sulla compatibilità Fare molta attenzione quando si scrive codice per le intestazioni HTTP. Per ottenere la massima compatibilità con tutti i client, la paorla-chiave "Basic" deve essere scritta con una "B" maiuscola, la stringa realm deve essere racchiusa in virgolette doppie (non singole), ed esattamente uno spazio deve precedere il codice 401 nella linea di intestazione HTTP/1.0 401.

Invece di stampare semplicemente PHP_AUTH_USER e PHP_AUTH_PW, probabilmente si vorrà controllare la validità dello username e della password. Probabilmente inviando una chiamata al database, o cercando un utente in un file dbm.

Si faccia attenzione ad alcune versioni di Internet Explorer. Sembra che siano molto schizzinosi riguardo all'ordine delle intestazioni. Inviare l'intestazione WWW-Authenticate prima dell'intestazione HTTP/1.0 401 sembra sistemare le cose per il momento.

A partire da PHP 4.3.0, al fine di prevenire che qualcuno scriva uno script che rivela la password di una pagina che era stata autenticata tramite un tradizionale meccanismo esterno, le variabili PHP_AUTH non verranno impostate se è abilitata l'autenticazione esterna per quella determinata pagina e modalità sicura è abilitato. Ciò nonostante, la variabile REMOTE_USER può essere usata per identificare un utente autenticato esternamente. Quindi, potete usare $_SERVER['REMOTE_USER'].

Nota: Nota sulla Configurazione PHP usa la presenza di una direttiva AuthType per determinare se viene utilizzata l'autenticazione esterna.

Si fa notare, però, che quanto scritto sopra non impedisce a qualcuno che controlla un URL non autenticato di sottrarre password da URL autenticati presenti sullo stesso server.

Sia Netscape Navigator che Internet Explorer cancellano la cache locale della finestra del browser, per quanto riguarda il realm, al ricevimento di una risposta 401 da parte del server. Questo è effettivamente un meccanismo di "log out" per l'utente, che lo forza a reinserire lo username e la password. Alcune persone usano questo per fare il "time out" dei login, o per rendere disponibili bottoni di "log-out&