Identification HTTP avec PHP

Les fonctions d'identification HTTP de PHP ne sont disponibles que si PHP est ex�cut� comme module Apache, et non pas sous la forme d'un CGI. Sous cette forme, il est possible d'utiliser la fonction header() pour demander une identification ("Authentication Required") au client, g�n�rant ainsi l'apparition d'une fen�tre de demande d'utilisateur et de mot de passe. Une fois que les champs ont �t� remplis, l'URL sera de nouveau appel�e, avec les variables pr�d�finies PHP_AUTH_USER, PHP_AUTH_PW et AUTH_TYPE contenant respectivement le nom d'utilisateur, le mot de passe et le type d'identification. Ces variables pr�d�finies sont trouv�es dans les tableaux $_SERVER et $HTTP_SERVER_VARS. Les m�thodes d'identification simple ("Basic") et de type "Digest" (depuis PHP 5.1.0) sont support�es. Reportez-vous � la fonction header() pour plus d'informations.

Note: Note sur les versions de PHP
Les superglobales, telles que $_SERVER, ont �t� ajout�es en PHP � partir de la version » 4.1.0.

Voici un exemple de script qui force l'identification du client pour acc�der � une page :

Exemple #1 Exemple d'identification HTTP simple

<?php
if (!isset($_SERVER['PHP_AUTH_USER'])) {
    
header('WWW-Authenticate: Basic realm="My Realm"');
    
header('HTTP/1.0 401 Unauthorized');
    echo 
'Texte utilis� si le visiteur utilise le bouton d\'annulation';
    exit;
} else {
    echo 
"<p>Bonjour, {$_SERVER['PHP_AUTH_USER']}.</p>";
    echo 
"<p>Votre mot de passe est {$_SERVER['PHP_AUTH_PW']}.</p>";
}
?>

Exemple #2 Exemple d'identification HTTP Digest

Cet exemple montre comment appliquer l'utilisation d'un script d'identification HTTP de type "Digest". Pour plus d'informations, lisez la documentation » RFC 2617.

<?php
$realm 
'Restricted area';

//utilisateur => mot de passe
$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(
'Texte utilis� si le visiteur utilise le bouton d\'annulation');
}

// analyse la variable PHP_AUTH_DIGEST
if (!($data http_digest_parse($_SERVER['PHP_AUTH_DIGEST'])) ||
    !isset(
$users[$data['username']]))
    die(
'Mauvaise Pi�ce d\'identit�!');


// G�n�ration de r�ponse valide
$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(
'Mauvaise Pi�ce d\'identit�e!');

// ok, utilisateur & mot de passe valide
echo 'Vous �tes identifi� en tant que : ' $data['username'];


// fonction pour analyser l'en-t�te http auth
function http_digest_parse($txt)
{
    
// protection contre les donn�es manquantes
    
$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$matchesPREG_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;
}
?>

Note: Note de compatibilit�
Soyez bien prudent lorsque vous utilisez des en-t�tes HTTP avec PHP. Afin de garantir un maximum de compatibilit� entre les navigateurs, le mot cl� "Basic" doit �tre �crit avec un B majuscule, et le texte de pr�sentation doit �tre plac� entre guillemets simples, et exactement un espace doit pr�c�der le code 401 dans l'en-t�te HTTP/1.0 401. Les param�tres d'authentification doivent �tre s�par�s par des virgules comme montr� dans l'exemple ci-haut.

Au lieu d'afficher simplement les variables globales PHP_AUTH_USER et PHP_AUTH_PW, vous pr�f�rerez s�rement v�rifier la validit� du nom d'utilisateur et du mot de passe. Par exemple, en envoyant ces informations � une base de donn�es, ou en recherchant dans un fichier dbm.

M�fiez-vous des navigateurs bogu�s, tels qu'Internet Explorer. Ils semblent tr�s susceptibles en ce qui concerne l'ordre des en-t�tes. Envoyer l'en-t�te d'identification (WWW-Authenticate) avant le code de HTTP/1.0 401 semble lui convenir jusqu'� pr�sent.

Pour �viter que quelqu'un �crive un script qui r�v�le les mots de passe d'une page, � laquelle on a acc�d� par une identification traditionnelle, les variables globales PHP_AUTH ne seront pas assign�es si l'identification externe a �t� activ�e pour cette page et que le safe mode est activ�. Dans ce cas, la variable REMOTE_USER peut �tre utilis�e pour identifier l'utilisateur � l'ext�rieur. De m�me que $_SERVER['REMOTE_USER'].

Note: Note de configuration
PHP utilise la pr�sence de la directive AuthType pour d�terminer si une identification externe est activ�e. �vitez donc cette directive de contexte si vous voulez utiliser l'identification de PHP (sinon, les deux identifications se contrediront, et �choueront).

Notez cependant que les manipulations ci-dessus n'emp�chent pas quiconque poss�de une page non identifi�e de voler les mots de passe des pages prot�g�es, sur le m�me serveur.

Netscape et Internet Explorer effaceront le cache d'identification client s'ils re�oivent une r�ponse 401. Cela permet de d�connecter un utilisateur, pour le forcer � saisir � nouveau son nom de compte et son mot de passe. Certains programmeurs l'utilisent pour donner un d�lai d'expiration ou, alors, fournissent un bouton de d�connexion.

Exemple #3 Identification HTTP avec nom d'utilisateur/mot de passe forc�

<?php
function authenticate() {
    
header('WWW-Authenticate: Basic realm="Test Authentication System"');
    
header('HTTP/1.0 401 Unauthorized');
    echo 
"Vous devez entrer un identifiant et un mot de passe valides pour acc�der
    � cette ressource.\n"
;
    exit;
}

if ( !isset(
$_SERVER['PHP_AUTH_USER']) ||
     (
$_POST['SeenBefore'] == && $_POST['OldAuth'] == $_SERVER['PHP_AUTH_USER'])) {
    
authenticate();
} else {
    echo 
"<p>Bienvenue : {$_SERVER['PHP_AUTH_USER']}<br />";
    echo 
"Ancien : {$_REQUEST['OldAuth']}";
    echo 
"<form action='{$_SERVER['PHP_SELF']}' METHOD='post'>\n";
    echo 
"<input type='hidden' name='SeenBefore' value='1' />\n";
    echo 
"<input type='hidden' name='OldAuth' value='{$_SERVER['PHP_AUTH_USER']}' />\n";
    echo 
"<input type='submit' value='Re Authenticate' />\n";
    echo 
"</form></p>\n";
}
?>

Ce comportement n'est pas n�cessaire par le standard d'identification HTTP Basic. Les tests avec Lynx ont montr� qu'il n'affectait pas les informations de session lors de la r�ception d'un message de type 401. Ce qui fait que presser la touche "retour" � un client Lynx pr�c�demment identifi� donnera l'acc�s direct � la ressource. Cependant, l'utilisateur peut utiliser la touche '_' pour d�truire les anciennes identifications.

Notez �galement qu'avant PHP 4.3.3, l'identification HTTP ne fonctionne pas sous le serveur Microsoft IIS avec la version CGI de PHP � cause d'une limitation de IIS. Pour que cela fonctionne en PHP 4.3.3+, vous devez �diter votre configuration de IIS "Directory Security". Cliquez sur "Edit" et activez uniquement "Anonymous Access", tous les autres champs doivent �tre laiss�s non actifs.

Une autre limitation si vous utilisez le module IIS (ISAPI) et PHP 4, vous ne devez pas utiliser les variables PHP_AUTH_* mais � la place, la variable HTTP_AUTHORIZATION est disponible. Par exemple, utilisez le code suivant : list($user, $pw) = explode(':', base64_decode(substr($_SERVER['HTTP_AUTHORIZATION'], 6)));

Note: Note pour les utilisateurs de IIS :
Pour que l'identification HTTP fonctionne avec IIS, la directive PHP cgi.rfc2616_headers doit �tre d�finie � 0 (la valeur par d�faut).

Note: Si le safe mode est activ�, le uid de ce script est ajout� � la partie realm des en-t�tes WWW-Authenticate.