Apache HTTP Authentication with PHP
At one time or another, we’ve all had to log into a password-protected Web site. When building a site, you may decide to require this of your visitors for several reasons. The first, and most obvious, is to protect secure information so that it can only be viewed by a select few. But you may also choose to assign usernames and passwords to casual visitors. This may be done in order to keep track of who is viewing your site, or to provide personalized options and services to your visitors.
The easiest way to password-protect a site is to use HTTP Authentication, where if a browser’s request for a protected page is not accompanied by the correct username and password, the Web server replies with an HTTP 401 error â€“ which means “Unauthorized Access” â€“ and an invitation for the browser to re-submit the request with a proper username and password. From the user’s point of view, most of this dialogue is hidden. Following that first failed request, the browser prompts the user (in a dialog box) for a username and password, and then re-submits the request, this time with the authentication information attached. Assuming the username/password combo is on the list of allowed users, the Web server then sends the page requested. The Web browser will likewise continue to send that username/password with all subsequent requests.
The most common way to set up an HTTP Authentication scheme is using an Apache “htaccess” file (see http://hoohoo.ncsa.uiuc.edu/docs/tutorials/user.html), but this method has disadvantages. Making the list of authorized users dynamic (so that users could register themselves and gain immediate access to your site, for example) can involve some pretty twisty server-side scripts that would have to manipulate the htaccess file(s) to add and remove users as appropriate. And keeping any kind of record as to who is accessing what using which username/password combinations is next to impossible using the basic support for HTTP Authentication in most Web servers.
Enter PHP, a free, open-source, cross-platform, server-side scripting language. When installed as an Apache module (this will not work with the CGI and ISAPI versions), PHP lets you handle HTTP Authentication by yourself, using any means you like to determine whether to accept or deny access to a Web site.
From here on I’ll assume that you are familiar with the basics of PHP. If this language is new to you, or if you need a refresher, Part 3 of my Building a Database-Driven Web Site series should bring you up to speed.
When installed as an Apache module, PHP provides two special global variables:
$PHP_AUTH_PW. These contain the username and password that accompanied the current HTTP request, respectively. Using PHP’s
header() function, you can then respond with an HTTP 401 error when the username, password, or both are incorrect.
Let’s look at some sample code for a page that may only be viewed if the user enters username
"myuser" and password
if ($PHP_AUTH_USER != "mysuser"
or $PHP_AUTH_PW != "mypass"):
// Bad or no username/password.
// Send HTTP 401 error to make the
// browser prompt the user.
header("WWW-Authenticate: " .
"Basic realm="Protected Page: " .
"Enter your username and password " .
header("HTTP/1.0 401 Unauthorized");
// Display message if user cancels dialog
<P>Without a valid username and password,
access to this page cannot be granted.
Please click 'reload' and enter a
username and password when prompted.
<?php else: ?>
...page contents here...
<?php endif; ?>
As you can see, checking the username and password entered is as simple as checking the variables
$PHP_AUTH_PW. When an incorrect user/pass combination is detected, you respond with two HTTP headers (using the PHP
WWW-Authenticate: Basic realm="Prompt the user here."
HTTP/1.0 401 Unauthorized
The first line informs the Web browser that Basic authentication is to be used. This just means that authentication is to be done with a username and password. The realm option lets the browser know when a particular username/password should be used when navigating throughout a group of Web pages. All pages that should use the same username/password (thus saving the user from having to re-enter them for every page) should have the same realm specified. Since this string is displayed in the dialog prompting the user, it’s an ideal place to put a message (for example: “If you’re a new user, enter ‘guest’ for your username and leave the password blank.”). Note that the double quotes in this line must be escaped with backslashes to prevent them from interfering with the double quotes surrounding the string in your PHP code.
The second line is a standard HTTP response code that lets the browser know that the username/password entered (if any) was incorrect, and that the user should be prompted to (re)enter them.
To protect an entire site, you would typically use PHP’s
include function to use the code that performs the username/password check in every file on your site that you want protected without having to retype said code on every page.
I recently used this technique on a site that I set up for a small group of people working on a project together. I issued a single username/password combination that gave them access to the registration page, where each of them would create a personal username/password combination. The registration page would store those combinations in a MySQL database (for more information on this, see my Building a Database-Driven Web Site article series). All the other pages on the site would then access that database to determine if a given username/password combination was allowed to access the site or not.
This and other creative possibilities for making your password protection system more flexible make HTTP Authentication using PHP an extremely handy tool to have in your arsenal.