PHP Essentials, 2nd Edition

Validating against a database alleviates the need for additional Web server configuration and increases Web server response times. Using the PHP authentication variables, you can still present the familiar username/password dialog box. Or, create a short HTML login form that requests a username and password. Whichever method you choose, you need to have access to a users table that holds username and password information.

Your table can be as simple or as complex as you want to make it. For the following examples, I've created a four-field users table in a MySQL database. The fields are id, real_name, username, and password.

Note 

You can use any database type to create and access a users table. See Chapter 3, "Working with Databases," for instructions on creating a table and accessing it via PHP for your specific database type.

Using PHP Authentication Variables to Validate Users

With a few minor additions to the authorize2.php script, you can validate the input from your authentication dialog box against usernames and passwords in the users table. Assume that the users table has been populated with the following information, where username is a unique field and password contains a hash of the actual passwords ("mypassword", "passme", and "gopass", respectively):

+----+------------+-----------+------------------+ | id | real_name | username | password | +----+------------+-----------+------------------+ | 1 | Jane Smith | jane | 162eebfb6477e5d3 | | 2 | Mary Smith | mary | 7bbdc9837f055863 | | 3 | John Smith | john | 26de36bb5818d066 | +-----+------------+-----------+-----------------+

The steps taken by the authorize3.php script, shown below, will:

  1. Display the username/password dialog box

  2. Accept the values.

  3. Open the database connection.

  4. Validate the values.

  5. Display the appropriate information.

    <?php // Check to see if $_SERVER[PHP_AUTH_USER] already contains info if (!isset($_SERVER[PHP_AUTH_USER])) { // If empty, send header causing dialog box to appear header('WWW-Authenticate: Basic realm="My Private Stuff"'); header('HTTP/1.0 401 Unauthorized'); echo 'Authorization Required.'; exit; } else { // If not empty, do something else // create connection; substitute your own information! $conn = mysql_connect("localhost","joeuser","34Nhjp") or die(mysql_error()); // select database; substitute your own database name $db = mysql_select_db("MyDB", $conn) or die(mysql_error()); // formulate and execute the query $sql = "SELECT id FROM users WHERE username='$_SERVER[PHP_AUTH_USER]' and password= password('$_SERVER[PHP_AUTH_PW]')"; $result = mysql_query($sql) or die (mysql_error()); // Present results based on validity, by counting rows. if (mysql_num_rows($result) == 1) { echo "<P>You are a valid user!<br>"; echo "You entered a username of $_SERVER[PHP_AUTH_USER] and a password of $_SERVER[PHP_AUTH_PW]</P>"; } else { echo "You are not authorized!"; } ) ?>

There are limitations to sending and receiving HTTP headers and PHP authentication variables. For example, once a user is authorized, a different user can't attempt to authorize himself within the current browser session. After processing the script and validating a user within the current browser session, the browser will not display the username/password dialog box again, because the browser doesn't know whether or not a different person is sitting in front of the machine. You must end the browser session, then restart the browser and access the protected area again in order to validate a different user. An additional problem is that no "global" authentication directive exists, such that which exists when you use an .htaccess file in a protected directory or create a <Directory></Directory> block in the Apache configuration file. When using PHP-based authentication, the authentication routine must be included at the beginning of each file you want to protect.

If you are querying a database for valid users, these additional requests will cause some slowdown in your server response times. Using an HTML form as a front-end to an authentication system has proven to be the most successful user authentication method in my own commercial applications. The database is queried on-demand, which provides accurate results as well as a consistently speedy server connection.

Using HTML Forms to Validate Users

Instead of sending HTTP authorization headers and displaying the username/password dialog box, create a simple form, called login.html, that asks for a username and password.

<HTML> <HEAD> <TITLE>My Login Form></TITLE> </HEAD> <!-- Configure the form --> <FORM ACTION="login.php" METHOD="post"> <!-- Create the form fields in a pretty table --> <table border=0> <tr> <td><strong>Username</strong></td> <td><input type="text" name="username" size="10" maxsize="10"></td> </tr> <tr> <td><strong>Password</strong></td> <td><input type="password" name="password" size="10" maxsize="10"></td> </tr> <tr> <td colspan="2" align="center"> <input type="submit" value="Validate Me"> </td> </tr> </table> </FORM> </BODY> </HTML>

When the user types values in the form fields and clicks on the Validate Me button, the values are sent to the login.php script (shown next). This script must hold the values, connect to the database, validate the user, and display the appropriate information. Essentially, only a few variable names will change from the authorize3.php script used earlier in this chapter. Instead of storing the username and password in $_SERVER[PHP_AUTH_USER] and $_SERVER[PHP_AUTH_PW], the values are stored in $_POST[username] and $_POST[password], as named by the form field names.

<?php // create connection; substitute your own information! $conn = mysql_connect("localhost", "joeuser", "34Nhjp") or die(mysql_error()); // select database; substitute your own database name $db = mysql_select_db("MyDB", $conn) or die(mysql_error()); // formulate and execute the query $sql = "SELECT id FROM users WHERE username='$_POST[username]' and password= password('$_POST[password]')"; $result = mysql_query($sql) or die (mysql_error()); // Present results based on validity. if (mysql_num_rows($result) == 1) { echo "<P>You are a valid user!<br>"; echo "Your username is $_POST[username]<br>"; echo "Your password is $_POST[password]</P>"; } else { echo "You are not authorized!"; } ?>

To take this process a step further, you can combine the HTML form and PHP script into one file using the include() function. By telling the script when to include the file containing the login form, you can display the form again without leaving this one script, should a user enter invalid entries (or none at all).

First, create a file called login_form.inc containing the following code:

<!-- Configure the form --> <FORM ACTION="login2.php" METHOD="post"> <input type="hidden" name="do" value="authenticate"> <!-- Create the form fields in a pretty table --> <table border=0> <tr> <td><strong>Username</strong></td> <td><input type="text" name="username" size="10" maxlength="10"></td> </tr> <tr> <td><strong>Password</strong></td> <td><input type="password" name="password" size="10" maxlength="10"></td> </tr> <tr> <td colspan="2" align="center"> <input type="submit" value="Validate Me"> </td> </tr> </table>

This code is simply the snippet of HTML that displays the form fields. The surrounding HTML will already be in the login2.php file, as you can intertwine HTML and PHP code in the same file.

<HTML> <HEAD> <TITLE>My Login Form</TITLE> </HEAD> <!-- Now we start our PHP code --> <?php // Continue a process, depending on the value of the $_POST[do] variable. // If this is the first time to access this script, the $_POST[do] variable // has no value. switch ($_POST['do']) { // if the value of $_POST[do] is "authenticate", continue this process case "authenticate": // create connection; substitute your own information! $conn = mysql_connect("localhost","root","3Kb7a*#1") or die(mysql_error()); // select database; substitute your own database name $db = mysql_select_db("thickbook_com", $conn) or die(mysql_error()); // formulate and execute the query $sql = "SELECT id FROM users WHERE username='$_POST[username]' and password= password('$_POST[password]')"; $result = mysql_query($sql) or die (mysql_error()); // Present results based on validity. if (mysql_num_rows($result) == 1) { echo "<P>You are a valid user!<br>"; echo "Your username is $_POST[username]<br>"; echo "Your password is $_POST[password]</P>"; } else { unset($_POST['do']); echo "<P>You are not authorized! Please try again.</P>"; // The next command automatically places the contents of // login_form.inc at this position; the HTML form fields will display. include("login_form.inc"); } break; default: // The default case, in this instance, means "if no value // exists for $_POST[do], or if no other case matches a value // for $_POST[do], display the login form." include("login_form.inc"); } ?> <!-- We have exited out of PHP code and are back in HTML --> </BODY> </HTML>

It's that simple to combine PHP and HTML into one comprehensive file that contains all the routines for querying a database, displaying error messages to unauthorized users, and providing custom content to valid users.

If you need to indicate to a subsequent script whether or not a user has been authenticated, it's not a good idea to pass the username and password in the URL using the GET method. Using the GET method would create a URL such as http://www.yourcompany.com/login2.php?username=jane&password=mypassword.

If a friend or coworker (or a random person off the street) looks over the user's shoulder at the browser, he will see the full URL in the Location area and will then know a valid username and password pair. Similarly, if the user bookmarks the page after a successful login, he will have bookmarked the complete URL, with the username and password. If the user shares a terminal with someone, or if a friend or coworker (or random person off the street) opens the browser and uses that bookmark, that person will have access to everything a correct username and password pair grants him.

In the next chapter, you'll learn to use cookies, those powerful little bits of text stored on a user's hard drive, to set and store variables and values you may need later, such as authentication variables. But right now, let's look at another simple method of restricting access.

Категории