Restricting Access Based on Cookie Values

Now for the fun part?using your cookie skills to restrict access to parts of your Web site! Suppose you created a login form that checked for values against a database. If the user is authorized, you send a cookie that says as much. Then, for all pages you want to restrict only to authorized users, you check for the specific cookie. If the cookie is present, the user can see the page. If the cookie is not present, the user is either sent back to the login form, or a message regarding access restrictions can be printed to the screen.

We'll go through each of these steps in the next few sections.

Creating the Authorized Users Table

When you're integrating user accounts into a Web-based application, it is most common to store the user-specific information in a database table. The information in this table can then be used to authorize the user and grant access to areas of the site that are specifically for these "special" users.

The following table creation command will create a table called auth_users in your MySQL database, with fields for the ID, first name, last name, email address, username, and password:

create table auth_users (
       id int not null primary key auto_increment,
       f_name varchar(50),
       l_name varchar(50),
       email varchar(150),
       username varchar(25),
       password varchar (75)

The following INSERT command puts a record in the auth_users table for a user named John Doe, with an email address of, a username of jdoe, and a password of doepass:

mysql> insert into auth_users values ('', 'John', 'Doe', '',
    -> 'jdoe', password('doepass'));
Query OK, 1 row affected (0.00 sec)

This INSERT command should be self-explanatory, with the exception of the use of the password() function. When this function is used in the INSERT command, what is stored in the table is in fact not the actual password, but a hash of the password.

When you view the contents of the auth_users table, you will see the hash in the password field, as follows:

mysql> select * from auth_users;
+ - - + - - - - + - - - - + - - - - - - - + - - - - - + - - - - - - - - - +
| id  | f_name  | l_name  | email         | username  | password          |
+ - - + - - - - + - - - - + - - - - - - - + - - - - - + - - - - - - - - - +
|  1  | John    | Doe     |  | jdoe      | 2fae5c9d478ec4b1  |
+ - - + - - - - + - - - - + - - - - - - - + - - - - - + - - - - - - - - - +
1 row in set (0.01 sec)


Although it may look like it is encrypted, a hash is in fact not an encrypted bit of information. Instead, it is a "fingerprint" of the original information. Hashes are generally used, like fingerprints, to perform matches. In this case, when you check your user's password, you will be checking that the hash of the input matches the stored hash. Using hashes alleviates the need?and security risk?of storing actual passwords.

Creating the Login Form and Script

After you authorize users in your table, you need to give them a mechanism for proving their authenticity. In this case, a simple two-field form will do, as shown in Listing 15.7.

Listing 15.7 User Login Form
  1: <html>
  2: <head>
  3: <title>Listing 15.7 User Login Form</title>
  4: </head>
  5: <body>
  6: <H1>Login Form</H1>
  7: <FORM METHOD="POST" ACTION="listing15.8.php">
  8: <P><STRONG>Username:</STRONG><BR>
  9: <INPUT TYPE="text" NAME="username"></p>
 10: <P><STRONG>Password:</STRONG><BR>
 11: <INPUT TYPE="password" NAME="password"></p>
 12: <P><INPUT TYPE="SUBMIT" NAME="submit" VALUE="Login"></P>
 13: </FORM>
 14: </body>
 15: </html>

Put these lines into a text file called listing 15.7.php, and place this file in your Web server document root. Next, you'll create the script itself, which the form expects to be called listing 15.8.php.

Listing 15.8 User Login Script
  1: <?php
  2: //check for required fields from the form
  3: if ((!$_POST[username]) || (!$_POST[password])) {
  4:     header("Location: listing15.7.php");
  5:     exit;
  6: }
  8: //connect to server and select database
  9: $conn = mysql_connect("localhost", "joeuser", "somepass")
 10:     or die(mysql_error());
 11: mysql_select_db("testDB",$conn) or die(mysql_error());
 13: //create and issue the query
 14: $sql = "select f_name, l_name from auth_users where username =
 15:    '$_POST[username]' AND password = password('$_POST[password]')";
 16: $result = mysql_query($sql,$conn) or die(mysql_error());
 18: //get the number of rows in the result set; should be 1 if a match
 19: if (mysql_num_rows($result) == 1) {
 21:    //if authorized, get the values of f_name l_name
 22:    $f_name = mysql_result($result, 0, 'f_name');
 23:    $l_name = mysql_result($result, 0, 'l_name');
 25:    //set authorization cookie
 26:    setcookie("auth", "1", 0, "/", "", 0);
 28:    //prepare message for printing, and user menu
 29:    $msg = "<P>$f_name $l_name is authorized!</p>";
 30:    $msg .= "<P>Authorized Users' Menu:";
 31:    $msg .= "<ul><li><a href=\"listing15.8.php\">secret page</a></ul>";
 33: } else {
 35:    //redirect back to login form if not authorized
 36:    header("Location: listing15.7.php");
 37:    exit;
 38: }
 39: ?>
 40: <HTML>
 41: <HEAD>
 42: <TITLE>Listing 15.8 User Login</TITLE>
 43: </HEAD>
 44: <BODY>
 45: <? print "$msg"; ?>
 46: </BODY>
 47: </HTML>

Put these lines into a text file called listing15.8.php, and place this file in your Web server document root. In a moment, you'll try it out, but first let's examine what the script is doing.

Line 3 checks for the two required fields from the form. They are the only two fields in the form: username and password. If either one of these fields is not present, the script will redirect the user back to the login form. If the two fields are present, the script moves along to lines 9?11, which connect to the database server and select the database to use, in preparation for issuing the SQL query to check the authenticity of the user. This query, and its execution, is found in lines 14?16. Note that the query checks the hash of the password input from the form against the password stored in the table. These two elements must match each other, and also belong to the username in question, in order to authorize the user.

Line 19 tests the result of the query by counting the number of rows in the resultset. The row count should be exactly 1 if the username and password pair represents a valid login. If this is the case, the mysql_result() function is used in lines 22?23 to extract the first and last names of the user. These names are used for aesthetic purposes only. Line 26 sets the authorization cookie. The name of the cookie is auth and the value is 1. If a 0 is put in the time slot, the cookie will last as long as this user's Web browser session is open. When the user closes the browser, the cookie will expire. Lines 29?31 create a message for display, including a link to a file we will create in a moment.

Finally, lines 33?38 handle a failed login attempt. In this case, the user is simply redirected back to the login form.

Go ahead and access the login form, and input the valid values for the John Doe user. When you submit the form, the result should look like Figure 15.1.

Figure 15.1. Successful login result.


Try to log in with an invalid username and password pair, and you should be redirected to the login form. In the next (and final) section, you will create the listing15.9.php script, which will read the authentication cookie you have just set and act accordingly.

Testing for the auth Cookie

The last piece of this puzzle is to use the value of the auth cookie to allow a user to access a private file. In this case, the file in question is shown in Listing 15.9.

Listing 15.9 Checking for auth Cookie
  1: <?php
  2: if ($_COOKIE[auth] == "1") {
  3:     $msg = "<p>You are an authorized user.</p>";
  4: } else {
  5:    //redirect back to login form if not authorized
  6:    header("Location: listing15.6.php");
  7:    exit;
  8: }
  9: ?>
 10: <html>
 11: <head>
 12: <title>Listing 15.8 Accessing a restricted page </title>
 13: </head>
 14: <body>
 15: <?php print "$msg"; ?>
 16: </body>
 17: </html>

From the menu shown in Figure 15.1, click the secret page link. Because you are an authorized user, you should see a result like Figure 15.2.

Figure 15.2. Accessing the secret page as an authorized user.


Close your browser and attempt to access listing15.9.php directly. You will find that you cannot, and will be redirected to the login form because the cookie is not set.

    Part III: Getting Involved with the Code