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.
Seulement les méthodes d'identification simple ("Basic") et de type "Digest"
sont supportées. Reportez-vous à la fonction
header() pour plus d'informations.
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, $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;
}
?>
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 double guillemets (pas des 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-dessus.
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.
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'] == 1 && $_POST['OldAuth'] == $_SERVER['PHP_AUTH_USER'])) {
authenticate();
} else {
echo "<p>Bienvenue : " . htmlspecialchars($_SERVER['PHP_AUTH_USER']) . "<br />";
echo "Ancien : " . 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";
}
?>
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.
Afin de rendre fonctionnel l'authentification HTTP avec un serveur IIS avec
la version CGI de PHP, vous devez éditer
votre configuration "Directory Security
". Cliquez
sur "Edit
" et activez uniquement
"Anonymous Access
", tous les autres champs doivent
être laissés non actifs.
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).