Tutorial: User Authentication
With PHP Session Management and MySQL

 


Richard H. Nilsson, August 15, 2004

Abstract

Describes the advantages of PHP Session and MySQL user authentication vs. HTTP Basic realm authentication. Provides a working example to authenticate a directory of PHP-enabled Web pages.

 


PHP Sessions

PHP version 3 and up provide built-in session management. The elements of session management include commands, session variables and methods to store and retrieve them. HTTP Basic authentication is less complex to implement but also less secure, and does not provide a clean way to "log out" other than actually quiting the browser application altogether. PHP session authentication requires a database of usernames and passwords, and code on each page to access sessions, save and retrieve authentication variables. In practice, the code is easily transportable and has a low operating overhead.

PHP sessions are started with the "session_start()" method. Starting a session generates a session file on the server and sends a cookie to the client containing the session_id, or name of the session. The default session name is PHPSSID. The session file contains variables set by code in your php script that you can access on any php-enabled page during the session.

Storing data in the session for later retrieval by other pages is accomplished by simply defineing the data variables. For example to save a user's name captured from posted form variables "fname" and "lname",

session_start();
$_SESSION['fname'] = $fname;
$_SESSION['lname'] = $lname;

is all that is required. Retrieving the variables later only requires:

session_start();
$fname = $_SESSION['fname'];
$lname = $_SESSION['lname'];
$passwd = $_SESSION['pass'];

It is a simple matter to then submit a SQL query to the site database to compare names and passwords with previously entered values.

Ending a session is accomplishe by invoking the "session_destroy()" method.

A Practical Example: The Login Page

Assume a MySQL database named "yourdb" has been created, containing a table called "Users" that holds Fname, Lname and Passwd fields for each user. The following code initiates the session and prompts for username and password with a simple form.

Farther on in the page we are going to have an HTML form the collects a username in the format "firstname.lastname" (notice the period). This is a user-friendly way to take both names in a single form blank.

Beginning at the top, before any HTML, we invoke the session creation method. Immediately we tell the Apache Web Server to hold off sending anything to the browser until we release it. This lets us do things like redirect to another page, or alter the page's name and layout as we progress through the code. Next we assume we're here for the first time, and set the page name variable to "Login". If we subsequently discover we've authenticated, we change the page title to its real name:

session_start();       // create a session
ob_start();            // hold off sending page to the browser just yet...
$page_title = "Login"; // page name if not logged in yet

I discuss how to setup a database and access it in another article, "PHP Tutorial, A Guestbook". Here, in the next 4 lines we show how we set up to connect and then actually connect to the database. The variables $hostName, $userName, $passWord, and $databaseName are contained in a hidden 'includes' file, "db.inc".

// set up access to the database
include 'includes/db.inc';     // file contains db access information
include 'includes/error.inc';  // prints any errors to page for debugging
                               // otherwise they would go to a log file
// connect to the database
if (!($db = @ mysql_connect($hostName, $userName, $passWord)))
   showError();
if (!( @ mysql_select_db($databaseName,$db)))
   showError();

Next, we check to see if we have invoked this page from the form with a 'submit' element present. If so, we breakdown the username (first.last) into two parts, and compare them with users info contained in the database.

// If logging in, set the session user and password
if (isset($_POST['submit']))
{
  // login form was submitted -- validate user agains the database
  $userArray = explode(".", stripslashes($_POST['login']));
  $passwd = stripslashes($_POST['passwd']);
  $firstn = ucfirst($userArray[0]);
  $lastn = ucfirst($userArray[1]);
  $result = mysql_query("
  SELECT * FROM $author 
  WHERE Fname='$firstn' 
  AND Lname='$lastn' 
  AND Passwd='$passwd'
  ",$db);

If the query is unsuccessful (the user is NOT in the database), we immediately kill the session and redirect the browser to reload the page ("$PHP_SELF").

  if (!$myrow = mysql_fetch_array($result))
  {
    session_destroy();
    // Restart for authorized user login
    exit;
    header("Location: $PHP_SELF");  // haven't sent to browser yet so we can retry
  } 

If the user is in the database, we don't leave, instead we set the session variables to pass the known valid user info to other functions and pages. We then rename the page, and release the output to the browser.

  $_SESSION['FNAME'] = $userArray[0];
  $_SESSION['LNAME'] = $userArray[1];
  $_SESSION['USERPASS'] = stripslashes($_POST['passwd']);
  $page_title = "Welcome";
} 
ob_end_flush();     // release output to the browser

Now, if we didn't come here via a form submission, the test on $_POST['submit'] whould have failed and we would bypass all this code and gone on to the form. First, we put the HTML page start code and HEAD tag stuff, including the page TITLE we set as a variable earlier. As previously mentioned, the form requests entry of username and password. The password is hidden. When the Enter key is hit or the "Login" button is clicked, the form is submitted to this page using a POST method to keep the information hidden, and we run through all the previously described the code -- and this time, that results in the session variables actually containing username and password, if the user validates against the database. Here's the form:

<head>
<title><?php echo $page_title;?></title>
.
.
     (put style sheets here)
.
.
</head>
<html>
<body>
.
.
     (you can put nice header titles and
      pictures here, if you like)
.
.
<?php
// L O G I N  F O R M ///////////////////////////////////
// Has she logged in and been granted a session?
if (!isset($_SESSION['USERPASS']))
{
?>
<h2>Please log in:</h2>
<form method="post" action="<?php echo $PHP_SELF;?>">
Username: <input name="login" type="text" value="" /><br />
Password: <input name="passwd" type="password" value="" /> 
          <input name="submit" type="submit" value="Log in" />
<?php
} else {
?>
.
.
      (the rest of the first page to show if we've 
       authenticated into the domain goes here)
.
.
<?php
}      // ends the "else"
?>
</body>
</html>

Other Site Pages

On other pages in the site, it is only necessary to check the session variables to establish that we've authenticated, and either redirect to the home page for authentication or show the page. Just put this code in the very top of the page, ahead of the opening <html> tag:

<?php
session_start();
ob_start();
$page_title = "Some Other Page";

// Authorization check
if (!isset($_SESSION['USERPASS']))
{
  $redirect_url = "index.php";
  header("Location: $redirect_url");
}
ob_end_flush;
?>