PHP  
downloads | documentation | faq | getting help | | php.net sites | links 
search for in the  
previousCr�ation d'imagesCookiesnext
Last updated: Tue, 11 Jun 2002
view this page in Printer friendly version | English | Brazilian Portuguese | Czech | Dutch | Finnish | German | Hungarian | Italian | Japanese | Korean | Polish | Romanian | Russian | Spanish | Turkish

Chapitre 17. Authentification HTTP avec PHP

Les fonctions d'authentification 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 authentification ("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 $PHP_AUTH_USER, $PHP_AUTH_PW et $PHP_AUTH_TYPE contenant respectivement le nom d'utilisateur, le mot de passe et le type d'authentification. Actuellement, seule l'authentification simple ("Basic") est support�e. Reportez-vous � la fonction header() pour plus d'informations.

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

Exemple 17-1. Exemple d'authentification HTTP

<?php
  if(!isset($PHP_AUTH_USER)) {
    Header("WWW-Authenticate: Basic realm=\"My Realm\"");
    Header("HTTP/1.0 401 Unauthorized");
    echo "Texte � envoyer si le client appuie sur le bouton d'annulation\n";
    exit;
  } else {
    echo "Bonjour $PHP_AUTH_USER.<P>"
    echo "Vous avez entr� le mot de passe $PHP_AUTH_PW.<P>"
  }
?>

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 bugg�s, tels que Internet Explorer. Ils semblent tr�s susceptibles concernant l'ordre des en-t�tes. Envoyer l'en-t�te d'authentification (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, � la quelle on a acc�d� par une authentification traditionnelle, les variables globales PHP_AUTH ne seront pas assign�es si l'authentification externe a �t� activ�e pour cette page. Dans ce cas, la variable $REMOTE_USER peut �tre utilis�e pour identifier l'utilisateur � l'ext�rieur.

Notez cependant que les manipulations ci-dessus n'emp�chent pas quiconque poss�de une page non authentifi�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'authentification client s'ils recoivent une r�ponse 401. Cela permet de d�connecter un utilisateur, pour le forcer � r�-entrer 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 17-2. Authentification 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 nom d'utilisateur valide et un mot de passe correct pour acc�der � cette ressource\n";
   exit;
  }
  if(!isset($PHP_AUTH_USER) || ($SeenBefore == 1 && !strcmp($OldAuth, $PHP_AUTH_USER)) ) {
   authenticate();
  }
  else {
   echo "Bienvenue $PHP_AUTH_USER<BR>";
   echo "Old: $OldAuth";
   echo "<form action=\"$PHP_SELF\" method=post>\n";
   echo "<input type=hidden NAME=\"SeenBefore\" VALUE=\"1\">\n";
   echo "<input type=hidden NAME=\"OldAuth\" VALUE=\"$PHP_AUTH_USER\">\n";
   echo "<input type=submit value=\"Re Authenticate\">\n"
   echo "</FORM>\n";
  }
?>

Ce comportement n'est pas n�cessaire par le standard d'authentification 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" (back) � un client lynx pr�c�demment authentifi� donnera l'acc�s direct � la ressource. Cependant, l'utilisateur peut utiliser la touche '_' pour d�truire les anciennes authentifications.

Notez aussi que tout ceci ne fonctionne pas sous Microsoft IIS et que les limitations de PHP en version CGI sont dues aux limitations de IIS.

User Contributed Notes
Authentification HTTP avec PHP
add a note about notes

21-Jul-1999 09:02

A few notes on authentication in which it's possible I overlooked some
things.  Considering a prior post about using the same salt for all users
so you can match passwords; I think it would be better to not do so, as
you can figure out the salt from the password and match.  (Example, salt
in DES if I'm not mistaken is the first 2 characters)
  Something I've been trying to figure out is secure apache module PHP on
a multi-user server.  
  Delima (with postgres)- any user can write a PHP page to read another
users databases.  Set your database to connect using username and
password, and any user can read your username and password from wherever
you place them.  (use PHP function to read it and as it has to be readable
by your web process for you to read it, they can)  
  The closest I've come to a solution for this is to run php as a CGI
module with suexec or cgiwrap.  
  Hopefuly someone else has a better solution; otherwise, something to
think about before you think of your databases as being secure with php
interfacing to them.


18-Dec-1999 12:42

Someone gave me a simple solution to the 'logout' problem: add some sort of
timestamp to the basic realm you send in the WWW_Authenticate header. Mine
now is: $realm="RealmName (
".strftime("%c",time())." )";. (btw: the problem
was: 1) IE4 asks for the page one more time after a 401, defeating sending
a 401 once to force a user to log on again. and 2) IE4 remembers the
password, and puts it default in the logon window. Changing the realm
solves these problems, not the 'logon failed' message of NS though).


02-Jan-2000 04:08

As an alternative check out PHPLIB at:


And the PHP Builder beginning/tutorial article called, "Session
Management and Authentication with PHPLIB" at 


09-Feb-2000 05:59

I had the same problem as above (that is, with apache I can't get the auth
info). The solution I found goes like this:

$headers = getallheaders();
$auth=$headers[authorization];
if ($auth=='') { $auth=$headers[Authorization]; }

if($auth=='')
{
	Header("WWW-Authenticate: Basic
realm=\"$PROG_NAME\"");
	Header("HTTP/1.0 401 Unauthorized");
}

list($user, $pass) = explode(":", base64_decode(substr($auth,
6)));


19-May-2000 08:31

Here is a code for the public sites enabling both logout bottom and timeout
using php+mysql. Working for both browsers.
The part "required" for each user protected page:

<?
function auth () {
        Header("WWW-Authenticate: Basic realm=\"ArmFN public
site\"");
        Header("HTTP/1.0 401 Unauthorized");
        echo "You have to authentificate yourself first \n";
        exit;
}

mysql_connect("localhost","train","") or
die("Unable to connect to SQL server"); 
mysql_select_db( "train") or die( "Unable to select
database"); 

if(!isset($PHP_AUTH_USER)) {

$timeout =
mktime(date(G),date(i)+10,0,date("m"),date("d"),date("Y"));
mysql_query("update users set login='$timeout' where id='$user' and
pasw='$pass'") or die("k");

	auth();

			} else {

    $pass = $PHP_AUTH_PW;
    $user = $PHP_AUTH_USER;

$nowtime =
mktime(date(G),date(i),0,date("m"),date("d"),date("Y"));
$quer2 = mysql_query("select * from users where id='$user' and
pasw='$pass' and login > '$nowtime'") or die("kuk2");

    if (mysql_num_rows($quer2) == "0") {
$timeout =
mktime(date(G),date(i)+10,0,date("m"),date("d"),date("Y"));
mysql_query("update users set login='$timeout' where id='$user' and
pasw='$pass'") or die("k");

auth();
}
		}
?>

You can have a "logout" bottom with hidden
$go="logout" form element and then have somewhere this part:

if ($do == "logout") {
mysql_connect("localhost","train","") or
die("Unable to connect to SQL server"); 
mysql_select_db( "train") or die( "Unable to select
database"); 
mysql_query("update users set login=0 where id='$PHP_AUTH_USER' and
pasw='$PHP_AUTH_PW'") or die("k");
}


30-Aug-2000 09:04

Good day.I've solved a problem where IE4 asks for the age one more time
after a 401, defeating sending a 401 once to force a user to log on
again.

  function  authenticate()  {
    setcookie("noauth","");
    Header( "WWW-authenticate:  Basic
realm=\"test\"");
    Header( "HTTP/1.0  401  Unauthorized");
	echo "You must enter user name";
   exit ;
  }
  if  (   !isset($PHP_AUTH_USER) ||  ($logoff==1) &&
$noauth=="yes"  )   {
	authenticate();
  }  

And logoff link -
 
<a
href="samehtml.phtml?logoff=1">Logoff</a></td>

Dmitry Alyekhin


16-Oct-2000 09:01

The new Mozilla browser doesn't seem to like the switched authentication
lines. 

This doesn't work (I have build 2000101308):

Header( "WWW-authenticate: Basic realm=\"test\"");
Header( "HTTP/1.0 401 Unauthorized");

The first time you authenticate all seems ok, but the second time it
always returns unauthorized.

This works as it should:

Header( "HTTP/1.0 401 Unauthorized");
Header( "WWW-authenticate: Basic realm=\"test\"");


20-Nov-2000 07:46

If you were trying to read the contents of $PHP_AUTH_USER or $PHP_AUTH_PW
from inside a function, you would first have to globalize them:

function Authenticat () {
    global $PHP_AUTH_USER;
    global $PHP_AUTH_PW;

    ...
}

Otherwise, PHP assumes that those variables are local to the function
Authenticate () and initializes them with NULL values.


28-Nov-2000 11:00

When calling in a function and using the $PHP_AUTH_USER and $PHP_AUTH_PW
against mysql connect I found I needed to omit the isset call and just
do:
if(!$PHP_AUTH_USER or !$PHP_AUTH_PW). Otherwise the
mysql_connect('host',$PHP_AUTH_USER,$PHP_AUTH_PW) call returns a value.
Also, in the checking for mysql_connect return value, I need to include
the auth headers again to get things working as expected.


10-Mar-2001 08:19

I suggest to read RFC2617 (HTTP Authentication: Basic and Digest Access
Authentication) and related RFCs.


05-Apr-2001 05:19

Thanks to [email protected] for the rfc note needed to solve this
one. This looks like it flushed out the authentication headers on both
Netscape and IE:
Header("WWW-Authenticate: Basic realm=\"Whatever Realm\",
stale=FALSE");


17-May-2001 09:55

You may enjoy this tutorial :


12-Jun-2001 09:53

This is a good resource for setting up htaccess schemes:



The windows version of apache comes with htpasswd.exe in the apache\bin
directory.

The only thing that present problems is you have to change your .htaccess
file to point to the created password file (ie
C:\directory\passwords.file)....so if you transfer the file back to a *nix
server it wont find your file.

One (temporary) workaround is changing your local httpd.conf file to point
to a different access file:

AccessFileName htaccess.

You just have to make sure to syncronize your access files.

Im not sure if you can point your htaccess to two password files??
 AuthName "restricted stuff"
 AuthType Basic
 AuthUserFile /usr/local/etc/httpd/users
 AuthUserFile C:\directory\password.file
 require valid-user


12-Jul-2001 07:51

If register_globals is turned off PHP_AUTH_USER and PHP_AUTH_PW variables
will not be set, instead they are stored in $HTTP_SERVER_VARS array as
$HTTP_SERVER_VARS['PHP_AUTH_USER'] and HTTP_SERVER_VARS['PHP_AUTH_PW'].

roberi[at]gmx[dot]net
15-Dec-2001 03:45

in 4.1.0 the variables are:

$_SERVER["PHP_AUTH_USER"]  and 
$_SERVER["PHP_AUTH_PW"]


28-Jan-2002 12:49

Does anyone know how to do the opposite ie: passing a username and password
to the http server in order for it to authenticate a given protected
directory???


28-Jan-2002 05:25

Restrict access by username, password AND ip address:

<?
function authenticate() {
	header("WWW-Authenticate: Basic realm=\":-!\"");
	header("HTTP/1.0 401 Unauthorized");
	print("You must enter a valid login username and password 
		to access this resource.\n");
	exit;
	}
if(!isset($PHP_AUTH_USER)){ authenticate(); }
else {
	$c=mysql_pconnect("server.name","user","password");
	mysql_select_db("dbname",$c);
	$q=sprintf("SELECT username,password FROM authenticateTable
		WHERE username='%s' AND password=PASSWORD('%s') 
		AND ipaddress='%s'",
			$PHP_AUTH_USER,$PHP_AUTH_PW,$REMOTE_ADDR);
	$q=mysql_query($q);
	if(mysql_num_rows($q)==0){ authenticate(); } 
}
?>


29-Jan-2002 09:00

To get it to work with IIS try using this code before setting your
"$auth = 0" and the "if (isset($PHP_AUTH_USER) &&
isset($PHP_AUTH_PW))"

//////////////////////////////////////////

if ($PHP_AUTH_USER == "" && PHP_AUTH_PW == ""
&& ereg("^Basic ", $HTTP_AUTHORIZATION)) 
{ 
  list($PHP_AUTH_USER, $PHP_AUTH_PW) = 
    explode(":", base64_decode(substr($HTTP_AUTHORIZATION, 6)));

}

//////////////////////////////////////////

It worked for me on IIS 5 and PHP 4 in ISAPI


22-Feb-2002 06:09

I tried the method posted by
[email protected] for a logout feature, which seems to be a problem for
users of http authentication. Tigran's method is perfect, except that
after you log out, you can STILL access the pages by clicking on
"cancel" when prompted again by the Java window. 
This will trigger the 401 error. But it will also create an entry in the
history folder. 

You will notice the "forward" button on your browser becomes
clickable. You only have to click on the that "forward" button
to be able to access the protected pages. 

I have found a solution for this problem by using a little Javascript to
refresh to another page.

Please go to my website for details:


28-Feb-2002 11:49

I use apache's built in support for .htaccess, and the following function
to grab user details as required.

Function GetHttpAuth()
{
        $headers = getallheaders();
        $auth=explode(" ",$headers[Authorization]);
if ($auth=='') { $auth=explode(" " ,$headers[authorization]); }

        $authdec=base64_decode($auth[1]);
        $autharray=explode(":",$authdec);
        $authname=$autharray[0];
        $authpass=$autharray[1];
        return($autharray);
}


22-May-2002 10:34

NOTE: For users of 4.2.0 and later. For this to work, you must deal with
the issue of the external variables not being registered in the global
scope by default. The quickest fix is to add register_globals = on to your
php.ini.


24-May-2002 01:55

If you want to access $PHP_AUTH_USER or $PHP_AUTH_PW variables via the
$GLOBALS variable, here is the good path:

$GlOBALS[_SERVER][$PHP_AUTH_USER] and $GlOBALS[_SERVER][$PHP_AUTH_PW]

In the messages above [_SERVER] was unspecified.

This is useful when you want to unset those variables in a function; then your test for the HTTP login prompt would be:

if ((!isset($PHP_AUTH_USER)) || ($PHP_AUTH_USER=="") { header("WWW-Authenticate: Basic realm=\"Login process\""); header("HTTP/1.0 401 Unauthorized"); ... } else { if ( =>here test if log/pass are the good one<= ) { ... ok } else { $GLOBALS['_SERVER']['PHP_AUTH_USER'=""; ...error message, user could log again } }



24-May-2002 02:22

The definitive HTTP authorization code:

function login_error()
{
 echo "error - login process failed."
}

if (!isset($PHP_AUTH_USER))
{
 header("WWW-Authenticate: Basic realm=\"Mosaic Authorization
process\"");
 header("HTTP/1.0 401 Unauthorized");

 //Result if user hits cancel button
 login_error();
}
else
{

 //check the login and password
 if('=>test on login and password<=')
 {
  //User is logged
  ...
  ...
 }
 else
 {
  //This re-asks three times the login and password.
  header( "WWW-Authenticate: Basic realm=\"Test Authentication
System\"");
  header("HTTP/1.0 401 Unauthorized");

  //Result if user does not give good login and pass
  login_error();
 }
}


02-Jun-2002 05:29

Using the same salt for all things is a bad idea.

Use the first two letters of the username - this also makes moving to
other .htaccess based systems easier :)

05-Jun-2002 08:08
A more elegant way to force a new name/password, cf. example 17-2 (if you
don't mind passing the old user in the query string):

<?
if (isset($PHP_AUTH_USER))
{
	if (!isset($prev_user))
	{
		header("Location: );
		exit;
	}
	else
	{
		if ($PHP_AUTH_USER == $prev_user)
		{
			header('WWW-Authenticate: Basic realm="Secure"');
			header('HTTP/1.0 401 Unauthorized');
			exit;
		}
	}
}
else
{
	header('WWW-Authenticate: Basic realm="Secure"');
	header('HTTP/1.0 401 Unauthorized');
	exit;
}
?>

The final set of headers is necessary because some browsers seem to unset
$PHP_AUTH_USER when the location header is sent.


07-Jun-2002 06:13

Hi,
Sometimes IE even after closing page remembers $PHP_AUTH_USER and
$PHP_AUTH_PW . is there any way to clean this buffer ?
Thanks.


19-Jun-2002 09:05

Now with the new super globals, these variables are stored in the $_SERVER
super global. Just use $_SERVER["PHP_AUTH_USER"] and
$_SERVER["PHP_AUTH_PW"] for PHP 4.1.x and higher.

20-Jun-2002 03:30
Seems that REMOTE_USER is only set in .htaccess Authentification not in PHP
header Authentifications


22-Jun-2002 08:32

Does anyone know how to do the opposite ie: passing a username and password
to the http server in order for it to authenticate a given protected
directory???


22-Jun-2002 08:59

Does anyone know how to do the opposite ie: passing a username and password
to the http server in order for it to authenticate a given protected
directory???


23-Jun-2002 09:15

Put it directly into the URL ?



27-Jun-2002 06:03

Is it possible to change these variables manually?

$_SERVER["PHP_AUTH_USER"]
$_SERVER["PHP_AUTH_PW"]

that way, it would be easy to make a logout script.

add a note about notes
previousCr�ation d'imagesCookiesnext
Last updated: Tue, 11 Jun 2002
show source | credits | stats | mirror sites:  
Copyright © 2001, 2002 The PHP Group
All rights reserved.
This mirror generously provided by:
Last updated: Sat Jul 6 20:06:19 2002 CEST