Hudzilla.org - the homepage of Paul Hudson
Contents > Networks > HTTP Wish List | Report Bug | About Me ]

15.4.3     Authentication over HTTP

This is NOT the latest copy of this book; click here for the latest version.

HTTP authentication traditionally takes the form of .htaccess files scattered around various directories webmasters want to keep private. A typical .htaccess file, combined with a .htpasswd file, contains information about users that are allowed access to a directory and their password.

Even though Apache allows you to customise these permissions, the system is far from flexible - hand-editing files each time you add users, or having to group authorised users together by password is a little behind the times.

HTTP authentication is mostly just a matter of sending special HTTP headers to your client asking them to provide access codes, and it is straightforward to implement in PHP as long as you have configured PHP to run as an Apache module (see previous issue for our installation guide). Let's look at basic authentication by creating the file auth.php, which should look like this:

<?php
    
if (!isset($_SERVER['PHP_AUTH_USER'])) {
        
header("WWW-Authenticate: Basic realm=\"Private Area\"");
        
header("HTTP/1.0 401 Unauthorized");
        
// only reached if authentication fails
        
print "Sorry - you need valid credentials granted access to the private area!\n";
        exit;
    } else {
        
// only reached if authentication succeeds
        
print "Welcome to the private area, {$_SERVER['PHP_AUTH_USER']} - you used {$_SERVER['PHP_AUTH_PW']} as your password.";
    }
?>


Braces are used inside our final print statement because we are printing out a value from inside an array, and the braces tell PHP to treat $_SERVER['PHP_AUTH_USER'] as an array variable that needs replacing with its value.

To start the authentication process, we send two HTTP headers using PHP's header() function. With header(), you can send any HTTP header you want, so long as you send them all before you send any HTML. I will be mentioning header() in several subsequent articles, but right now we are just interested in the WWW-Authenticate header and HTTP status codes.

WWW-Authenticate allows us to define the area, or _realm_, to which we are limiting access. It might be "Internet Mail Gateway", "Members Area", or, in our example, "Private Area". This realm name is usually shown to users when they are prompted for their username and password.

The second header() function sends the HTTP status "401", which means "no access". This most often means no username and password have been entered, but it may also mean the details entered were incorrect. Therefore, while WWW-Authenticate tells the browser what response is required to authenticate, the 401 header says "no entry" - you need both to perform authentication.

If your user clicks "Cancel" they should be presented with something other than a blank page. In our example above, we have the print line beginning "Sorry - you need valid" ready for this eventuality.

The last print statement, "Welcome to the private area" is for people who have authenticated successfully. All it takes to authenticate currently is a username and password - we don't check the values of the data, we just accept whatever they give us.

if (!isset($_SERVER['PHP_AUTH_USER'])) {

That line forms the crux of authentication with PHP. When users submit authentication, PHP receives the username and password as $_SERVER['PHP_AUTH_USER'] and $_SERVER['PHP_AUTH_PW'] respectively. By checking whether $_SERVER['PHP_AUTH_USER'] is set, we are saying, "Have we received an authentication username from the client?" If we have not, we send a request for authentication using WWW-Authenticate and exit the script.

When our visitors provide a username and password, the script is called again. This time the 'if' statement evaluates to true and we print out our welcome message. Most sites would want to perform some sort of username and password checking in order to make authentication worthwhile, so let us change the script to include simple credentials checking.

<?php
    
if (!isset($_SERVER['PHP_AUTH_USER'])) {
        
header("WWW-Authenticate: Basic realm=\"Private Area\"");
        
header("HTTP/1.0 401 Unauthorized");
        print
"Sorry - you need valid credentials to be granted access!\n";
        exit;
    } else {
        if ((
$_SERVER['PHP_AUTH_USER'] == 'paul') && ($_SERVER['PHP_AUTH_PW'] == 'hudson')) {
            print
"Welcome to the private area!";
        } else {
            
header("WWW-Authenticate: Basic realm=\"Private Area\"");
            
header("HTTP/1.0 401 Unauthorized");
            print
"Sorry - you need valid credentials to be granted access!\n";
            exit;
        }
    }
?>

The modified script above now only allows users that provide the username 'paul' and the password 'hudson'. We have two conditions combined using AND (&&), which means that the 'if' statement only evaluates to true if the username is 'paul' and the password is 'hudson'.

Our system is now more powerful, but we still need to hard code usernames and passwords for everyone we want to have access to our realm.





<< 15.4.2 Reading queued headers: headers_list()   15.4.4 Dynamic authentication >>
Table of Contents
Want to see this stuff in print? PHP in a Nutshell takes the core topics covered here, adds in thousands of edits from the editorial team and myself, and combines them to make an unbeatable reference for PHP programmers at all levels.



My latest book has hundreds more tips on how to use PHP, Apache, and MySQL, plus Perl, Python, shell scripts, performance tuning, and more!



Top-right shadow
 
Bottom-left shadow Bottom shadow

Comments from other readers
Be the first to add a comment to this chapter!



Add comment
Please note that by posting a comment here you are committing it to the public domain. This is important so that others can make use of your code themselves, and also so that I can incorporate helpful notes directly into the main text. Comments are limited to 2000 characters in length.

If you are reporting an error in the content, please tell me directly.

Your name/email address:
Your comment:
 
Now, in order to verify that you're a real person, please answer this simple question: what is seven plus two?
The answer is:
(please write in
numbers, eg 19)


Top-right shadow
 
Bottom-left shadow Bottom shadow