Where are we?

You know how sessions let PHP pages share information. You’ve seen how we can store data about users and their permissions in a database table.

Now let’s create the log in system that uses that data.

This lesson’s goals

You will learn that:

The log in form gets a user name and password from the user.

It sends the data to a page that checks whether the user name and password is in the database table users.

If the user name and password are found, permission information is stored in the session.

Overview

We want the user to see a log in form, like this:

Figure 1. Louise logs in

If the user name and password match a record in the database, then the user would see the admin menu.

Figure 2. Admin menu

Here are the pages we’ll create:

Figure 3. Pages involved in log in

log-in.php shows the form. The user completes it, and clicks the submit button. log-in.php passes the data to check-log-in.php. check-log-in.php checks the database for a matching record in the users table. If it finds one, it stores some data in the session, and sends the browser to the admin menu page, admin/index.php. If there is no matching record, the browser is sent back to the log in form.

Let’s look at the code.

log-in.php

Here’s the log in form again:

Figure 1 (again). Louise logs in

The form does some error checking. There are client-side checks for empty fields:

Figure 4. Empty field errors

But what if the user fills in both fields with an unknown user name and password? This check cannot be done on the client-side. A server-side program has to look up the user name and password before finding that the user name/password combination is unknown.

Here’s the error reporting for a unknown user name/password combination:

...looks for the session variable logged in. If it has the value y, the user is already logged in. The browser is sent to the admin menu immediately, skipping the log in process.

Lines 14 to 18 are part of the templating system.

Lines 20 to 62 mostly implement client-side error checking. But lines 27 to 31 are new. They show errors from the server.

Here are the pages again:

Figure 3 (again). Pages involved in log in

check-log-in.php is the page that finds whether the user name and password are valid. If they aren’t, is sends something to log-in.php, to tell it to show an error message. But what should it send, and how?

Here’s one way to do it. When check-log-in.php finds an error, it tells the browser to jump to log-in.php. It attaches something to the URL. Here is some code from check-log-in.php :

header("location:$path_to_root/admin/log-in.php?err=auth");

See the err=auth bit? This tells log-in.php to show an authentication error. Here’s how the URL looks in a browser’s address bar:

Figure 7. Error flag in URL

When log-in.php receives this, it can show the error message.

We already have some JavaScript code in log-in.php for showing errors. It uses colors, shows an icon, and other Good Stuff. Let’s use that existing JavaScript code to report the server error.

An <input> field with a type of password is almost the same as one with a type of text. The only difference is that the browser doesn’t show what the user types into a password field:

Figure 9. Password field

check-log-in.php

Here are the pages again:

Figure 3 (again). Pages involved in log in

check-log-in.php gets a user name and password from log-in.php. It looks them up in the database. If they’re found, it sets some session data, and jumps to the admin menu. If the user name and password are not found, check-log-in.php jumps back to log-in.php.

Two things to notice. The first is the and. The select will only return records where both conditions are true.

The second thing is the binary keyword. MySQL tests are usually not case-sensitive. So louise, Louise, and lOUise are all the same.

But we don’t want that here. Applications are more secure if user names and passwords as case-sensitive, so louise and Louise are not the same. Adding the binary keyword makes the tests case-sensitive.

Line 25 is:

$record_set = $db->query($query);

It tells MySQL to run the query, returning a record set.

If the user name and password are valid, the record set should return exactly one record. That gets tested in the next piece of code.