This section assumes an understanding of HTTP. If you're not familiar with it, you'll find an introduction in Appendix D.
The HTTP standard provides support to authenticate and authorize user access. When a browser sends an HTTP request for a resource that requires authentication, a server can challenge the request by sending a response with the status code of 401 Unauthorized. When it receives an unauthorized response, the browser presents a dialog box that collects a username and password; a dialog box presented by a Mozilla browser is shown in Figure 11-1. After the username and password have been entered, the browser then resends the original request with an extra header field that encodes the user credentials.
The HTTP header just collects the name and password; it doesn't authenticate a user or provide authorization to access a resource or service. The server must use the encoded username and password to decide if the user is authorized to receive the requested resource. For example, you might configure your Apache web server to require authentication by using a file that contains a list of usernames and encrypted passwords. In another application, you might use a table of usernames and passwords stored in a database and develop PHP code for the authentication process.
Figure 11-2 shows the interaction between a web browser and a web server when a request is challenged. The user requests a resource stored on the server that requires authentication and the server sends back a challenge response with the status code set to 401 Unauthorized. Included in this response is the header field WWW-Authenticate that contains parameters that instruct the browser on how to meet the challenge. The browser may then need to prompt for a username and password to meet the challenge. The browser then resends the request, including the Authorization header field that contains the credentials the server requires.
The following is an example of an HTTP response sent from an Apache server when a request is made for a resource that requires authentication:
HTTP/1.1 401 Authorization Required Date: Thu, 2 Dec 2004 23:40:54 GMT Server: Apache/2.0.48 (Unix) PHP/5.0.0 WWW-Authenticate: Basic realm="Marketing Secret" Connection: close Content-Type: text/html; charset=iso-8859-1 <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html401/loose.dtd"> <html> <head> <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1"> <title>401 Authorization Required</title> </head> <body> <h1>Authorization Required</h1> This server could not verify that you are authorized to access the document requested. Either you supplied the wrong credentials (e.g., bad password), or your browser doesn't understand how to supply the credentials required. <p><hr> </body> </html>
The WWW-Authenticate header field contains the challenge method , instructing the browser how to collect and encode the user credentials. In the example, the method is set to Basic. The header also contains the name of the realm that the authentication applies to, in this case Marketing Secret. The realm is used by the browser as a key for a username and password pair, and it is also displayed when the credentials are collected.
Figure 11-1 shows the dialog displayed for the realm Marketing Secret. Once the browser has collected the credentials from the user, it resends the original request with an additional Authorization header field that contains the credentials. The following is an example of an HTTP request that contains credentials in the Authorization header field:
GET /auth/keys.php HTTP/1.1 Connection: Keep-Alive User-Agent: Mozilla/4.51 [en] (WinNT; I) Host: localhost Accept: image/gif, image/jpeg, image/pjpeg, image/png, */* Accept-Encoding: gzip Accept-Language: en Accept-Charset: iso-8859-1,*,utf-8 Authorization: Basic ZGF2ZTpwbGF0eXB1cw==
A browser can automatically respond to a challenge if credentials have previously been collected for the realm, and it will continue to include authorization credentials with requests until the browser program is terminated or another realm is entered.
The Basic encoding method sends the username and password in the Authorization header field after applying base-64 encoding. Base-64 encoding isn't designed to protect data and so isn't a form of encryption: it simply allows binary data to be transmitted over a network At best, it protects data from only casual inspection.
Some web servers, including Apache, support the Digest encoding method. The Digest method is more secure than the Basic method because the user's password isn't sent over the network. However, to use it, the browser must also include support. The major browsers that support digest authentication are Opera, Microsoft Internet Explorer, Amaya, Mozilla, and Netscape. Therefore, because digest authentication is not as widely implemented as basic authentication, you should use it only when you have control over your users' browser choice.
While the Basic encoding method provides no real security, the Secure Sockets Layer (SSL) protocol can protect the HTTP requests and responses sent between browsers and servers. This means that SSL also provides protection for the usernames and passwords sent with the Basic method. Therefore, for web database applications that transmit sensitive information, we recommend SSL be used. We discuss SSL later in this chapter.
The simplest method to restrict access to an application is to use your web server's built-in authentication support. The Apache web server can easily be configured to use HTTP authentication to protect the resources it serves. For example, Apache allows authentication to be set up on a directory-by-directory basis by adding parameters to the Directory setting in the httpd.conf configuration file.
The following example shows part of an httpd.conf file that protects the resources (such as HTML files, PHP scripts, images, and so on) stored in the /usr/local/apache/htdocs/auth directory:
# Set up an authenticated directory <Directory "/usr/local/apache/htdocs/auth"> AuthType Basic AuthName "Secret Mens Business" AuthUserFile /usr/local/apache/allow.users require hugh, dave, jim </Directory>
If you're using Microsoft Windows, you can replace /usr/local/apache/htdocs/auth with a directory such as C:\Program Files\EasyPHP1-7\www\auth. On a Mac OS X platform, use a directory such as /Library/WebServer/Documents/auth. In all cases, the auth directory must exist.
A user must pass the Apache authentication before access is given to resources?including PHP scripts?placed in an authenticated directory. The Apache server responds with a challenge to unauthorized requests for any resources in the protected directory. The AuthType is set to Basic to indicate the method used to authenticate the username and password collected from the browser, and the AuthName is set to the name of the realm. Apache authorizes users who are listed in the require setting by checking the username and password against those held in the file listed after the AuthUserFile directive. There are other parameters that aren't discussed here; you should refer to the Apache references listed in Appendix G for full configuration details.
If you don't have administrator or root access to your web server machine, you can still protect a directory (or selected resources in a directory). You do this by creating an .htaccess file in the directory you want to protect and include in it what resources are protected, who has access to them, and where to find the passwords. It's easy to use PHP to protect resources?as we discuss in the next section?we don't discuss this process in detail. You can find more information at http://httpd.apache.org/docs-2.0/howto/htaccess.html.
For many web database applications, Apache authentication provides a simple solution. However, when usernames and passwords need to be checked against a database, or when HTTP authentication can't meet the needs of the application, authentication can be managed by PHP instead. The next section describes how PHP can manage HTTP authentication directly without configuring Apache. Later, we also describe how to provide authentication without using HTTP.