PHP: PHP による HTTP 認証 - Manual
PHP  
downloads | documentation | faq | getting help | mailing lists | | php.net sites | links | my php.net 
search for in the  
<機能クッキー(Cookies)>
view the version of this page
Last updated: Tue, 21 Dec 2004

第 33章PHP による HTTP 認証

PHP による HTTP 認証のフックは、Apache モジュールとして実行した時のみ 有効で、CGI 版では利用できません。Apache モジュール上の PHP スクリプトに おいては、header() 関数を使用して "Authentication Required" メッセージをクライアントブラウザに 送ることが可能です。 これにより、クライアントブラウザではユーザー名とパスワードの入力要求 ウインドウがポップアップ表示されます。一度、ユーザーがユーザー名と パスワードを入力すると、PHP スクリプトを含むその URL は、次回以降、 定義済みの変数 PHP_AUTH_USER と、 PHP_AUTH_PW と、 PHP_AUTH_TYPE にそれぞれユーザー名、 パスワード、認証型が代入された状態で呼ばれます。 定義済みの変数は、配列 $_SERVER および $HTTP_SERVER_VARS でアクセス可能です。 "Basic" 認証のみがサポートされています。詳細は、 header()を参照下さい。

PHP バージョンに関する注意: $_SERVERのような オートグローバルは、 PHPバージョン 4.1.0 で利用可能です。 $HTTP_SERVER_VARSは、PHP 3以降で利用可能です。

ページ上でクライアント認証を強制するスクリプトの例を以下に示します。

例 33-1. HTTP 認証の例

<?php
 
if (!isset($_SERVER['PHP_AUTH_USER'])) {
  
header("WWW-Authenticate: Basic realm=\"My Realm\"");
  
header("HTTP/1.0 401 Unauthorized");
   echo
"ユーザーがキャンセルボタンを押した時に送信されるテキスト\n";
   exit;
  } else {
   echo
"<p>こんにちは、{$_SERVER['PHP_AUTH_USER']} さん。</p>";
   echo
"<p>あなたは、{$_SERVER['PHP_AUTH_PW']} をパスワードとして入力しました。</p>";
  }
?>

互換製に関する注意: HTTPヘッダ行をコーディングする際には注意を要します。全てのクライアントへの 互換性を最大限に保証するために、キーワード "Basic" には、 大文字の"B"を使用して書くべきです。realm文字列は(一重引用符ではなく) 二重引用符で括る必要があります。また、HTTP/1.0 401 ヘッダ行のコード 401 の前には、 1つだけ空白を置く必要があります。

単に PHP_AUTH_USERおよびPHP_AUTH_PW を出力するのではなく、ユーザー名とパスワードの有効性をチェックしたいと 思うかもしれません。 その場合、クエリーをデータベースに送るか、ある dbm ファイル中の ユーザーを調べるといったことをすることになるでしょう。

バグのある Internet Explorer ブラウザには注意してください。このブラ ウザは、ヘッダの順序に関してとてもうるさいようです。今のところ、 HTTP/1.0 401 ヘッダの前に WWW-Authenticate ヘッダを送るのが効果があるようです。

PHP 4.3.0 以降、誰かが従来の外部機構による認証を行ってきたページの パスワードを暴くようなスクリプトを書くことを防ぐために、 特定のページに関して外部認証が可能でかつ セーフモード が有効の場合、 PHP_AUTH 変数はセットされません。 この場合、外部認証されたユーザーかどうかを確認するために REMOTE_USER 変数、すなわち、 $_SERVER['REMOTE_USER'] を使用することができます。

設定上の注意: PHP は、外部認証が動作しているかどうかの判定を AuthType ディレクティブの有無で行います。

しかし、上記の機能も、認証を要求されないURLを管理する人が同じサーバー にある認証を要するURLからパスワードを盗むことを防ぐわけではありませ ん。

サーバーからレスポンスコード 401 を受けた際に、Netscape Navigatorおよび Internet Explorer は共にローカルブラウザのウインドウ上の認証キャッシュを 消去します。この機能により、簡単にユーザーを"ログアウト"させ、強制的に ユーザー名とパスワードを再入力させることができます。この機能は、 "タイムアウト" 付きのログインや、"ログアウト" ボタンに適用されています。

例 33-2. 新規に名前 / パスワードを入力させる HTTP 認証の例

<?php
 
function  authenticate() {
  
header('WWW-Authenticate: Basic realm="Test Authentication System"');
  
header('HTTP/1.0 401 Unauthorized');
   echo
"このリソースにアクセスする際には有効なログインIDとパスワードを入力する必要があります。\n";
   exit;
  }

  if (!isset(
$_SERVER['PHP_AUTH_USER']) || ($_POST['SeenBefore'] == 1 && $_POST['OldAuth'] == $_SERVER['PHP_AUTH_USER'])) {
  
authenticate();
  } 
  else  {
   echo
"<p>Welcome: {$_SERVER['PHP_AUTH_USER']}<br>";
   echo
"Old: {$_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";
  }
?>

この動作は、HTTP Basic 認証の標準に基づいていません。よって、この機能に 依存しないように注意する必要があります。Lynx によるテストの結果、 Lynx は、認証証明書を 401 サーバー応答によりクリアしないことが明らかに なっています。このため、back を押してから foward を再度押すことにより 証明書の要件が変更されない限りリソースをオープンすることができます。 しかし、ユーザは '_' キーを押すことにより認証情報をクリアすることが可能です。

PHP4.3.3 までは、Microsoft の IIS サーバーと CGI 版の PHP の組み合わせでは、 この機能は、IIS の制約により使用することができなかったことにも 注意して下さい。PHP 4.3.3 以降においてこの機能を使用するには、 IIS の設定の "ディレクトリセキュリティ" の "編集" ボタンを押して "匿名アクセス" のみをオンにしてください。その他のフィールドは オフのままにしてください。

他の制限としては、IIS モジュール (ISAPI) を使用している場合に、 PHP_AUTH_* 変数が使用できないことがあります。 しかし、代わりにHTTP_AUTHORIZATION を使うことができます。 例えば、次のようなコードを考慮してください。list($user, $pw) = explode(':', base64_decode(substr($_SERVER['HTTP_AUTHORIZATION'], 6)));

IIS に関する注意:: IIS上 で HTTP 認証を使用する場合、PHP の cgi.rfc2616_headers ディレクティブは0 (デフォルト値) にセットされて いなければなりません。

注意: セーフモード が有効の場合、 WWW-Authenticateヘッダの realm部にスクリプトの uid が追加されます。



add a note add a note User Contributed Notes
PHP による HTTP 認証
ernstp at winzerware dot de
09-Nov-2004 07:05
Don't like passwords at home or simply don't want access with passwords maybe told form one to another...

You make a configuration file like that:

# Passwort for special IP-Range
IP 192.168.0.
axel:PGWAiIeUxcHOg
sven:ADD1IDbsVHSEo

# Following IP works without password (Keyword 'ALL')
IP 192.168.0.4
ALL

# Passwords for the rest of the world
IP
ernst:INo9dSzfU5sRU
sven:ADD1IDbsVHSEo

<?
$path_log
= "/home/ernst/.htmyway";

// Konfigurationsfile einlesen:
$file = file($path_log);

$login = FALSE;                    // Gets TRUE, when login is valid
$ip = 'world';                    // This is the currend IP while reading the configuration
$access = 'world';                // IP from configuration fitting into $_SERVER['REMOTE_ADDR']

foreach ($file as $zeile)
{
  
$zeile = trim($zeile);

   switch(
true)
   {
       case (
strlen($zeile) == 0 ):                // break for empty lines
          
break;

       case (
substr($zeile, 0, 1) == '#' ):            // break for Komments
          
break;

       case (
substr($zeile, 0, 2) == 'IP' ):        // change IP range
          
$ip = substr($zeile, 3);
           if (
$ip == '')
              
$ip = 'world';

           if (
ereg("^$ip", $_SERVER['REMOTE_ADDR']) )    // fitting IP
          
{
              
$access = $ip;
           }
           break;

       case (
ereg("(.+):(.*)", $zeile, $reg) ):        // scan passwords
          
$logray[$ip][$reg[1]] = $reg[2];
           break;

       case (
$zeile == 'ALL' ):                // if no login is needet
          
$logray[$ip]['all'] = 1;
   }
}

// <for testing>
if ( isset($_GET['logout']) )
{
   unset(
$_SERVER['PHP_AUTH_USER']);
   unset(
$_SERVER['PHP_AUTH_PW']);
}
//  </for testing>

// authorisation test
if ( isset($_SERVER['PHP_AUTH_USER']) AND isset($_SERVER['PHP_AUTH_PW']) )
   if( isset(
$logray[$access][$_SERVER['PHP_AUTH_USER']]) )
       if(
$logray[$access][$_SERVER['PHP_AUTH_USER']] == crypt($_SERVER['PHP_AUTH_PW'], (substr($logray[$access][$_SERVER['PHP_AUTH_USER']], 0, 2))) )
          
$login = TRUE;

if ( isset(
$logray[$access]['all']) )
  
$login = TRUE;

// send login-form if needet
if ( !$login )
{
  
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;
}

// Your running programm...
if ( $login )
{
   echo
"Hello " . $_SERVER['PHP_AUTH_USER'];

?>
<BR>
<form>
<input type='submit' name='logout' value='logout'>
</form>
<?

}
?>
bernard dot paques at bigfoot dot com
24-Sep-2004 04:42
The approach described in the manual works only at servers where PHP is ran as an Apache module. Where PHP is ran as a CGI module, credentials are always empty, whether the user actually fills the authentication box or not.

Apparently the set of Apache variables exposed to PHP is restricted when PHP runs in CGI mode, and this explains why $_SERVER['PHP_AUTH_USER'] and $_SERVER['PHP_AUTH_PW'] are not set.

The solution is to select one Apache variable actually transmitted to PHP even in CGI mode, and to put in it authentication data submitted by the browser.

Look at the following directive added to the .htaccess file:

<IfModule mod_rewrite.c>
   RewriteEngine on
   RewriteRule .* - [E=REMOTE_USER:%{HTTP:Authorization},L]
</IfModule>

This directive states that, if mod_rewrite is available, credentials gathered from the HTTP header Authorization are put into the $_SERVER['REMOTE_USER'] variable.

To build up on RFC 2617 on HTTP Authentication, if the surfer wishes to send the userid "Aladdin" and password "open sesame", the browser will add the following header attribute to the HTTP request:

Authorization: Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ==

Thanks to the rewrite directive put in .htaccess, the triggered PHP script will catch credentials through $_SERVER['REMOTE_USER'] as follows:

$_SERVER['REMOTE_USER'] = Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ==

From there all you have to do is to decode base64 credentials, and to split the string to retrieve user name and password, as described into the RFC 2617.

Before you use $_SERVER['PHP_AUTH_USER'] and $_SERVER['PHP_AUTH_PW'], check if these variables are empty.

If yes, attempt to rebuild them by using $_SERVER['REMOTE_USER'].

The following snippet does exactly that:

<?php
// maybe we have caught authentication data in $_SERVER['REMOTE_USER']
if((!$_SERVER['PHP_AUTH_USER'] || !$_SERVER['PHP_AUTH_USER'])
   &&
preg_match('/Basics+(.*)$/i', $_SERVER['REMOTE_USER'], $matches)) {
   list(
$name, $password) = explode(':', base64_decode($matches[1]));
  
$_SERVER['PHP_AUTH_USER'] = strip_tags($name);
  
$_SERVER['PHP_AUTH_PW']    = strip_tags($password);
}
?>

The full script used to build a secured RSS feed is available here:



Of course, this trick works only if the mod_rewrite module is available, and if you have changed the .htaccess file as explained above.
jason
15-Aug-2004 05:12
on the php+mysql auth code by tigran at freenet dot am

There are some security weaknesses.

First
$user
  and
$pass

are both insecure, they could leave this code open to SQL injection, you should always remove invalid characters in both, or at least encode them.

Actually storing passwords as MD5 hashes leaves you less work to secure.

Second security risks
The same mysql user has rights to both update and select, and possibly even insert and on your auth database no less.
Again the SQL inject attack may occur with this., and the end user could then change the users username, password, or anything else in relation to this.

Third items is more of a performance issue,
 
Do you really need to update the database, as updates are slower then selects, and if you do them every time they access the page, you are costing some speed penalty. 

One option, if you want to use sql (I think mysql has it) is memory only databases, and create a table within memory, the stores a unique session identifier for each user, that is logged in, or alternatively if it's a single front end system, you could use db files.
php at cscott dot net
12-Aug-2004 11:18
Note that Microsoft has released a 'security update' which disables the use of username:password@host in http urls.

  

The methods described above which rely on this will no longer work in Microsoft browsers, sadly.

You can re-enable this functionality as described at

  

but your users will probably be unwilling to do this.
chris at schaake dot nu
17-Jun-2004 04:42
A simple script for SSL Client Certificate authentication with a basic authentication fall-back. I use this on my site using LDAP server to check username/passwords and client certificate to user mapping.

<?
// Check if and how we are authenticated
if ($_SERVER['SSL_CLIENT_VERIFY'] != "SUCCESS") { // Not using a client certificate
  
if ((!$_SERVER['PHP_AUTH_USER']) && (!$_SERVER['PHP_AUTH_PW'])) { // Not logged in using basic authentication
      
authenticate(); // Send basic authentication headers
  
}
}

if (
$_SERVER['SSL_CLIENT_S_DN_CN'] != "chris") { // Check CN name of cert

  
if (!(($_SERVER['PHP_AUTH_USER'] == "test") && ($_SERVER['PHP_AUTH_PW'] == "123"))) { // Check username and password
      
authenticate(); // Send basic authentication headers because username and/or password didnot match
  
}
}

phpinfo();

// Call authentication display
function authenticate() {
  
Header("WWW-Authenticate: Basic realm=Website");
      
Header("HTTP/1.0 401 Unauthorized");
      
error401();
       exit;
}
?>

See my website () for more details on client certificate with Apache and PHP.
mcbethh ( at ) [no spam] op.pl
06-Jun-2004 05:25
There is a nice way to 'fix' missing REMOTE_USER env variable when using PHP as CGI, using mod_rewrite rule like this:

RewriteRule .* - [E=REMOTE_USER:%{HTTP:Authorization},L]
nuno at mail dot ideianet dot pt
13-May-2004 10:33
In Windows 2003 Server/IIS6 with the php4+ cgi I only get HTTP authentication working with:
<?php header("Status: 401 Access Denied"); ?>
with
<?php header('HTTP/1.0 401 Unauthorized'); ?>
doesn't work !
I also need in "Custom Errors" to select the range of "401;1" through "401;5" and click the "Set to Default" button.
Thanks rob at theblip dot com
steuber at aego dot de
07-May-2004 11:15
Quite a good solution for the logout problem:

Just tell browser that it is successfully logged in!
This works as follows:
1. User clicks logout button
2. Script sends 401 Header
3. User does NOT enter a password
4. If no password is entered, script sends 200 Header

So the browser remembers no password as a valid password.

Example:

<?php
if (
       (!isset(
$_SERVER['PHP_AUTH_USER']))
   ||(
           (
$_GET["login"]=="login")
   && !(
             (
$_SERVER['PHP_AUTH_USER']=="validuser")
             && (
$_SERVER['PHP_AUTH_PW']=="validpass")
           )
       )
   ||(
           (
$_GET["logout"]=="logout")
     && !(
$_SERVER['PHP_AUTH_PW']=="")
       )
     ) {
Header("WWW-Authenticate: Basic realm=\"Realm\"");
Header("HTTP/1.0 401 Unauthorized");
echo
"Not logged out...<br>\n";
echo
"<a href=\"index.php?login=login\">Login</a>";
exit;
} else if (
$_SERVER['PHP_AUTH_PW']=="") {
echo
"Logged out...<br>\n";
echo
"<a href=\"index.php?login=login\">Login</a>";
exit;
}
?>
najprogramato at post dot sk
27-Apr-2004 12:08
Don't use apache authentification in plain text. Is more better to use own script to generete new ID which is relevant to password. Apache auth data are sent to every page, so the posible mistake are known.
ian AT iyates DOT co DOR uk
05-Mar-2004 01:32
In my use of HTTP Authentication, I've found that some Apache setups swap around the usual variables.
Here's the fix I made so that you can still use PHP_AUTH_USER and PHP_AUTH_PW. Hope it helps someone

<?php
## Apache server fix ##
if (isset($_SERVER['PHP_AUTH_USER']) && !isset($_ENV['REMOTE_USER']))
  
$_ENV['REMOTE_USER'] = $_SERVER['PHP_AUTH_USER'];
if (isset(
$_SERVER['AUTH_PASSWORD']) && !isset($_ENV['PHP_AUTH_PW']))
  
$_ENV['PHP_AUTH_PW'] = $_SERVER['AUTH_PASSWORD'];
?>
rob at theblip dot com
04-Mar-2004 04:47
Regarding HTTP authentication in IIS with the php cgi 4.3.4, there's one more step. I searched mightily and didn't find this information anywhere else, so here goes. When using HTTP auth with the php CGI, you need to do the following things:

1. In your php.ini file, set "cgi.rfc2616_headers = 0"

2. In Web Site Properties -> File/Directory Security -> Anonymous Access dialog box, check the "Anonymous access" checkbox and uncheck any other checkboxes (i.e. uncheck "Basic authentication," "Integrated Windows authentication," and "Digest" if it's enabled.) Click OK.

3. In "Custom Errors", select the range of "401;1" through "401;5" and click the "Set to Default" button.

It's this last step that is crucial, yet not documented anywhere. If you don't, instead of the headers asking for credentials, IIS will return its own fancy but useless 'you are not authenticated' page. But if you do, then the browser will properly ask for credentials, and supply them in the $_SERVER['PHP_AUTH_*'] elements.
ken_php_net at wolfpackinteractive dot com
25-Dec-2003 09:16
Say you have password and groups files in standard Apache format (htpasswd etc.), but you want to apply authorization based on something other than filename, ie something you can't catch in .htaccess.  You want to emulate the server behavior in PHP -- the equivalent of:

AuthType Basic
AuthName "Members"
AuthUserFile /path/to/.htpasswd
AuthGroupFile /path/to/.groups
require group Members

Here's what I came up with:

<?PHP

$AuthUserFile
= file("/path/to/.htpasswd");
$AuthGroupFile = file("/path/to/.groups");
$group = "Members";
$realm = "Members";

function
authenticate(){
  
header("WWW-Authenticate: Basic realm=\"$realm\"");
  
header('HTTP/1.0 401 Unauthorized');
   echo
"You must enter a valid user name and password to access the requested resource.";
   exit;
}

for(;
1; authenticate()){
   if (!isset(
$HTTP_SERVER_VARS['PHP_AUTH_USER']))
       continue;

  
$user = $HTTP_SERVER_VARS['PHP_AUTH_USER'];
   if(!
preg_grep("/$group: $user$/", $AuthGroupFile))  # (format assumptions)
      
continue;

   if(!(
$authUserLine = array_shift(preg_grep("/$user:.*$/", $AuthUserFile))))
       continue;

  
preg_match("/$user:((..).*)$/", $authUserLine, $matches);
  
$authPW = $matches[1];
  
$salt = $matches[2];
  
$submittedPW = crypt($HTTP_SERVER_VARS['PHP_AUTH_PW'], $salt);
   if(
$submittedPW != $authPW)
       continue;

   break;
}

echo
"You got in!"
?>
Paul
08-Nov-2003 11:53
Here is a extremely easy way to successfully logout.

<?php
if ( $realm == '' )
$realm = mt_rand( 1, 1000000000 );
  
header( 'WWW-Authenticate: Basic realm='.$realm );
?>

To log the user out simply change the value of $realm
bela - iandistudio
20-Oct-2003 05:40
Hi there. Thought long and hard to come up with a logout mechanism that erases the variables $PHP_AUTH_USER and $PHP_AUTH_PW. Finally came up with something, it is better than nothing, hope somebody will find it usefull:

logout.php:

<?
header
("Location: ".$PHP_SELF);
exit;
?>

"EnterYourUserName" and "YourPassword" will be the two variables new value, while "ServerRoot" is your server's domainname (like www.somedomain.com).
You should ensure, that nobody will use "EnterYourUserName" as it's login name.

Happy coding.
ad_ver at inbox dot ru
04-Sep-2003 02:54
Modified script from "jonhaynes at bigfoot dot com" using Oracle logon

<?php
function authenticate() {
header("WWW-Authenticate: Basic realm=\"My 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(
$_SERVER['PHP_AUTH_USER'])){ authenticate(); }
else {
  
$conn = @ OCILogon($_SERVER['PHP_AUTH_USER'], $_SERVER['PHP_AUTH_PW'], "orcl92") ;
   if(!
$conn)
       {
authenticate(); }
   else {
OCILogoff($conn);};
}
?>
steve at topozone dot com
16-Jun-2003 07:51
The method described in the text does not appear to work with PHP in cgi mode and Apache-2.x. I seems that Apache has gotten stricter or introduced a bug such that you can initiate the authentication, but Apache seems to try to  authenticate the browser response which always fails because it does not know what to authenticate against and the headers never get passed back to the PHP script.

I didn't try it with PHP as a module.
25-Apr-2003 12:02
@emmanuel dot keller at net2000 dot ch:
The behaviour you report bases on the fact that PHP installed as a CGI program must send CGI status messages instead of HTTP return codes. Therefore, anywhere you normally send "HTTP/1.0 xyz", you have to send "Status: xyz".
JKi
14-Feb-2003 11:38
To clear HTTP authentication cache in Internet Explorer (6 SP1 and later), use "ClearAuthenticationCache" command.

document.execCommand("ClearAuthenticationCache");
emmanuel dot keller at net2000 dot ch
14-Jan-2003 10:14
Some servers won't support the HTTP1.0 specification and will give an error 500 (for instance). This happened with a server where I uploaded an authentication script.

If it happens, you can try the HTTP1.1 header syntax :

<?php
header
("WWW-Authenticate: Basic realm=\"My Realm\"");
header('status: 401 Unauthorized');
?>
yaroukh at email dot cz
12-Jan-2003 12:42
Here is my solution - works in MSIE and Mozilla.

I use http-authentication only for the first time user accesses his
private page; after valid username and password are provided, he is
recognized using his sessionID and ip ...
the reasons are following:
1) when users changes his password it is not required instantly
   (I find this quite comfortable)
2) auto-login function works fine (unless user click logout)

And here's how i works ...

The "trick" is to pass a temporary username+password to the browser.
(I call it "temporary" because no user account matching these
parameters is neccessary.)

The most essential thing is the following link on user's private page:

===
<?  $url = "".
      
$username.    // see note 1
      
":".
      
Session_ID().  // see note 2
      
"@localhost/".PROJECT_NAME."/logout.phtml";
?>
<a href="<?=$url?>">logout</a>
===

1) we pass the actual username because MSIE uses this username as
   a "default pre-fill" for the login-window and some hash-string
   would confuse the users.
2) the temporary password is not too important, but there are
   two things we expect from it:
   a) we need to know this string in the logout.phtml script
   b) the string definetely should not match the user's password
     (otherwise user gets logged back instantly); using current
     Session_ID() we are pretty sure this won't happen

This link causes that the temporary login-params are available in
the logout.phtml script.
Using "www-authenticate" header in the logout.phtml script we force
the browser to accept our temporary login-params. (I suppose browser
actually repeats the request and the next time it checks
the login-params sent in the URL; but this is only my guess and
it is not important.)

The logout.phtml code:
===
<?  $query = "UPDATE users SET sessionID = NULL ".
      
"WHERE sessionID = '".Session_ID()."'";
    
$mysql->query($query);
    
// because we (me :o) use the sessionID and the ip for
     // the identification we need to clean the sessionID; (I found it
     // a little bit easier to destroy the sessionID in the db than
     // unsetting the cookie and/or destroying+restarting
     // the current session)

    
if($PHP_AUTH_PW != Session_ID()) {
      
// keep asking for the login-params untill PHP_AUTH_PW returned
       // by the browser matches the current Session_ID() (which means
       // that the browser accepted the temporary login-params
       // we sent to it AND FORGOT THE REAL ONES)

      
Header("HTTP/1.0 401 Unauthorized");
      
Header("WWW-Authenticate: Basic realm=\"".PROJECT_NAME."\"");
   }
?>
<html>
   <head>
       <meta http-equiv="author" content="yaroukh at email dot cz">
       <title><?=PROJECT_NAME?></title>
       <link rel="stylesheet" href="style.css" type="text/css">
   </head>
   <body>
         <a href="<?=PROJECT_NAME?>/main.phtml">continue</a>
   </body>
</html>
===

About the "continue" link: the link is not too important, but using it
we can get rid off the temporary login-params which wouldn't look
too aesthetically in the address-bar. :o)
admin at creationfarm dot com
07-Aug-2002 06:24
I have written a class for HTTP Authentication in PHP. Anyone looking for a shortcut can get it from:

Feel free to make suggestions and contributions to the class. It needs some improvement.
05-Jun-2002 09: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.
louis dot carlier at ngroups dot com
24-May-2002 03:22
The definitive HTTP authorization code:

<?php
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();
 }
}
?>
lenny at phpkingdom dot com
22-Feb-2002 08: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:
sjeffrey at inquesis dot com
29-Jan-2002 11: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))"

<?php
//////////////////////////////////////////

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
philip at cornado dot com
17-May-2001 10:55
You may enjoy this tutorial :
k u d o s at t e l u s p l a n e t dot n e t
05-Apr-2001 06: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");
owld at mail dot ru
30-Aug-2000 10: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.

<?php
 
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
tigran at freenet dot am
19-May-2000 09: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");
}
rratboy at pobox dot com
09-Feb-2000 07: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:

<?php
$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)));

<機能クッキー(Cookies)>
 Last updated: Tue, 21 Dec 2004
show source | credits | sitemap | contact | advertising | mirror sites 
Copyright © 2001-2005 The PHP Group
All rights reserved.
This unofficial mirror is operated at: /
Last updated: Mon Mar 14 08:13:06 2005 Local time zone must be set--see zic manual page