Practical Example - Login System for Dreamweaver Hotel

Chapter 9 - Hand Coding Within Dreamweaver MX
byGareth Downes-Powellet al.
Wrox Press 2003

Now that we've looked at the new hand-coding features of Dreamweaver MX, we're going to create a login system, so that the staff at the Dreamweaver Hotel can log in and view client bookings.

In this example, we're going to hand code some PHP to perform the following actions:

  • Read in the values from a custom-made login form.

  • Verify the correct type of data is contained in the form values.

  • Encrypt the password.

  • Verify the username and encrypted password against the values stored in the database.

  • Display either a failure notice or a success notice to the user, and set a session containing the user's status.

We'll be using the idea of a session throughout this example, so it needs a little explanation here. A session starts when a user first browses to a page on a particular web site, and ends a certain length of time after they last request a page for that site. This means it can be used to keep track of a user throughout their visit to a site. In particular, we'll be using it to keep track of whether the user has logged in or not.

Overview of Our Login System

Listed below are the login pages we are going to be creating, and how they link to each other. The first three pages are to be stored in a folder called admin in the root site directory. The final page is to be stored in a folder called include, also in the root site directory.

login.php

This page allows users to log in. Only users with a valid username and password that are checked against the database can log in - they are then redirected to menu.php. Their status is saved in a session for checking on other pages. If their details are incorrect, they stay on the login.php page, and an error message is shown.

menu.php

This page shows a menu of options to users who have successfully logged in, and who have either "Staff" or "Admin" status. It redirects any non-logged in users back to the login.php page.

create_user.php

This page is linked to by menu.php, but can only be accessed by managers who have "Admin" status. It can be used to add a new user to the database, after validating the data and encrypting the user's password. It redirects any users with "Staff" status back to the menu.php page.

dreamweaver_hotel_admin.php

This is purely a PHP file; there is no HTML code. It contains our generic functions, which can be used on any page which has an include statement pointing to this file.

The Database Users Table

Our first step is to create a users table in the database, to hold the user details for the Dreamweaver Hotel staff.

Below is the structure for the users table:

Field Name

Field Type

Notes

ID

integer(8)

Primary Key, Auto increment

username

varchar(20)

Stores staff member's username

password

varchar(20)

Stores staff member's password

firstName

varchar(30)

Stores staff member's first name

lastName

varchar(30)

Stores staff member's last name

status

varchar(10)

Stores staff member's admin status

The SQL Query below will create this table when executed:

    CREATE TABLE 'users' (    'ID' INT(8) NOT NULL AUTO_INCREMENT PRIMARY KEY,    'username' VARCHAR(20) NOT NULL,    'password' VARCHAR(20) NOT NULL,    'firstName' VARCHAR(30) NOT NULL,    'lastName' VARCHAR(30) NOT NULL,    'status' VARCHAR(10) NOT NULL    ) ; 

You can create the table through the MySQL command line, or with your favorite MySQL Administration tool.

Create Users Page - The Layout

The first page we'll create is a page to add users to the users table, which we'll call create_users. php. It contains the following form fields:

    <form name="createuser" method="post" action="<?php echo($PHP_SELF) ?>">      <input name="firstName" type="text"  maxlength="30">      <input name="lastName" type="text"  maxlength="30">      <input name="username" type="text"  maxlength="20">      <input name="password" type="password"  maxlength="20">      <input name="confirmpassword" type="password"               maxlength="20">      <select name="status" >        <option value="Admin">Admin</option>        <option value="Staff" selected>Staff</option>      </select>      <input type="submit" name="Submit" value="Create User">    </form> 

Look at the action attribute for the <form> element above, and you'll see it's set to:

    <?php echo($PHP_SELF) ?> 

$PHP_SELF is one of the built-in PHP variables. When the code is run, it is replaced with the location of the current page. We use this because we want the form to submit the data back to the same page. If in future we change the location of this page, the code will still work with no changes necessary.

Lay the form out in a similar manner to the form below, using the template for the Dreamweaver Hotel developed in Chapter 5:

click to expand

Save the page as create_users.php, and place it in a directory called admin, off the site root.

We now need to add the PHP code, which will make the page dynamic.

At first, we'll ignore the security checks so that we can use our create_users .php page to add our main admin record. We'll add security checks to it later.

Our first task is to create our PHP include file (dreamweaver_hotel_admin.php) containing custom functions we are going to use to validate various aspects of the form data.

These are all generic functions that can be used on any site, rather than being specially written for our Hotel Admin system. This is an area where the Snippets panel really becomes useful, as over time you can build a library of such PHP functions, and then just insert the snippets you're going to need into your include file.

Using an include file containing generic functions keeps your page neater, and easier to read and debug. All specific functions, which are hard coded to do a specific job on that page only, can be stored in the page code, keeping them separate from the generic functions.

The PHP Include File

Our include file will be called dreamweaver_hotel_admin.php, and will be stored in a directory called include, which is in the site root.

The include file contains many functions, each listed one after the other. We'll discuss each of these functions separately to avoid confusion.

trim_data()

    function trimdata($formdata)    {    //Trim any leading or trailing spaces    //$formdata = Form Data Array    foreach ($formdata as $key=> $value)    {    $new_array[$key] = trim($value);    }    return $new_array;    } 

This function is passed an array of form data. It works through this array, and trims any leading or trailing spaces from both the key to the array and the value stored at that key. The function returns the trimmed array.

check_form()

    function check_form($formdata)    {      // Check all fields are filled in      // $formdata = Form Data Array      foreach ($formdata as $key => $value)      {        if (!isset($key) || $value == "" )        return false;     }      return true;    } 

When passed an array of the form data, this function works through each form field checking that the value in the array is not empty for every key in the array that has been set.

If any fields are left blank, the function returns false, otherwise the function returns true.

check_password_length()

    function check_password_length($formdata, $password, $minlen)    {      // Check that password is required length      // $formdata = Form Data Array      // $password = Name of password field      // $minlen = Minimum number of password characters      if (strlen($formdata[$password]) < $minlen)        return false;      else        return true;    } 

This function is passed an array containing the form data, the name of the password field, and the minimum number of password characters allowed. If the password is less than the minimum number of characters allowed, then the function returns false, otherwise it returns true.

confirm_password()

    function confirm_password($formdata, $password1, $password2)    {      // Check that two passwords given match      // $formdata = Form Data Array      // $password1 = Name of first password field      // $password2 = Name of second password field      if ($formdata[$password1] === $formdata[$password2])        return true;      else        return false;    } 

This function is passed an array of form data, and the names of both the password, and the confirm password field. It then checks that both password fields are identical, and returns true if they are, and false if they are not.

check_unique()

    function check_unique($formvalue, $db, $dbhost, $dbuser, $dbpassword, $table,    $field)    {      // Checks a table in a database, to see if passed value already exists      // $formvalue = Value you are checking to see whether it is unique      // $db = mySQL Database Name      // $dbhost = mySQL Server address, for example localhost      // $dbuser = mySQL user name      // $dbpassword = mySQL password      // $table = mySQL Table to search      // $field = mySQL Field to search      $error = "";      // Connect to the mySQL Server      $mysql = mysql_connect($dbhost, $dbuser, $dbpassword);      if(!$mysql)      {        $error = "Cannot connect to Database Host";        return($error);      }      // Open the mySQL Database      $mysqldb = mysql_select_db($db);      if(!$mysqldb)      {        $error = "Cannot open Database";        return($error) ;      }      // Query Table to see if $formvalue is unique      $myquery = "SELECT * FROM $table WHERE $field = '$formvalue'";      $result = mysql_query($myquery);      if (!$result)      {        $error = "Cannot run Query";        return($error);      }      // Get number of Records found, should be 0 if $formvalue is unique      $unique = mysql_num_rows($result);      if ($unique > 0)      {        $error = $formvalue. " already in use";        return($error);      }      // Return true if $formvalue is unique      return("true");    } 

This is the last, and the longest, function in our include file. The purpose of the function is to take the form value that is passed to it and check it against a field in a table in the database, to see if the value already exists or not. For example, we'll be using this function to check whether an entered username already exists in the database.

The function is passed the form value, the database name, the database host, the database username and password, and the field and table names you wish to check. The function then connects to the database, and opens the table with a WHERE clause that searches for the passed form value in the passed field. It then checks to see if any records are returned from the database.

If there are no records returned, the function returns true, and the value will be unique when added to the database. If a record is returned, the value will not be unique, so the function returns an error message. If there are any errors connecting to the database, these are also returned by the function.

You can see that any of the functions we've described above could be used in any site without changes. It's a good idea to make your functions generic, because you'll soon end up with a library of code, which will save you from having to waste time rewriting code in the future. A good idea would be to add the functions to the Snippets panel (as detailed earlier in the chapter), allowing you to quickly insert them into a PHP include file in the future.

Create Users Page - Adding the Code

We're now going to add the PHP code to the create users page (create_users.php) we started earlier, to make the page validate the form data and insert the new user into the users table.

Switch to Code view, and scroll to the top of the page. The first line to add goes before the <HTML> tag - it includes our file dreamweaver_hotel_admin.php.

    <?php include ("../include/dreamweaver_hotel_admin.php"); ?> 

We'll now create three more pieces of PHP code, that are added after this include line.

insert_data()

First, we create a function that inserts our form data into the users table.

    <?php    function insert_data($formdata)    {      // Insert Data into users table      // $formdata = form array      // set up database connection variables      $error = "" ;      $myhost = "localhost";      $myuser = "php";      $mypass = "password";      $mydb = "php";      // set up data to insert      $firstName = $formdata['firstName'];      $lastName = $formdata['lastName'];      $username = $formdata['username'];      $password = $formdata['password'];      $status = $formdata['status'];      // encrypt the password using the key "DWMXPHP"      $password = crypt($password,"DWMXPHP");      // connect to mySQL server      $mysql = mysql_connect($myhost, $myuser, $mypass);      if (!$mysql)      {        $error = "Cannot connect to mySQL server";        return($error);      }      // Connect to Database      $mysqldb = mysql_select_db($mydb, $mysql);      if (!$mysqldb)      {        $error = "Cannot open database";        return($error);      }      // Insert Data      $myquery = "INSERT INTO users ( firstName, lastName, username, password, ";      $myquery .= "status) VALUES ('$firstName', '$lastName', '$username', ";      $myquery .= "'$password', '$status' ) ";      $result = mysql_query($myquery, $mysql);      if (!$result)      {        $error = "Cannot run Query";        return $error;      }      // Return True if record written successfully      return("true") ;    }    ?> 

This function takes the data from the form array that's passed to it, and puts the values into variables. It then encrypts the password, using the key "DWMXPHP", and this encrypted value is stored in the database. crypt () is a one-way hash function built into PHP, which means that once the data is encrypted, it can never be unencrypted again. To check against it, we encrypt the value to test with the same key, and if the two encrypted values match, we know the value is correct.

Next, we connect to the MySQL database, and insert the user data into the users table. The query returns true if the record is inserted correctly, otherwise it returns a relevant error message.

verify_data($formdata)

This next function validates the user data entered in the form on the page. If it is validated successfully, it calls the insert_data () function described above.

    <?php    function verify_data($formdata)    {      // This function uses the functions in the include file,      // and uses them to validate various aspects of the form.      // If validation fails, it returns $error, the appropriate error message      // If validation suceeds, return true      $error = "";      $form_data = trim_data($formdata);      $user = $form_data['username'];      // check all form fields are filled in      if (!check_form($form_data))      {        $error="All Form Fields must be filled in";        return($error);      }      // check password and confirmation password match      if (!confirm_password($form_data, 'password', 'confirmpassword'))      {        $error = "Password and Confirm Password do not match";        return($error);      }      // check length of password      if (!check_password_length($form_data, 'password', 5))      {        $error = "Password should be 5 characters or more";        return($error);      }      // check that username is unique      $check = check_unique($user, 'php', 'localhost' , 'php', '20012001', 'users',    'username');      if ($check != "true")      {        $error = "Username is already in use, select another";        return($error);      }      // if validated successfully, insert data into table      $insert_check = insert_data($formdata);      // if error with insertion, return error      if ($insert_check != "true")        return($insert_check);      // form validated and record inserted successfully      return("");    }    ?> 

This function uses the validation functions defined in our include file to verify that all the fields are filled in, that the password and confirmation password match, that the length of the password is correct, and that the chosen username is unique.

If all these validations are successful, the function calls the insert_data () function defined above, which inserts our user record into the users table. If everything is successful, the function returns nothing; otherwise the function returns the relevant error message.

Using the Functions

The last piece of code for this section is as follows:

    <?php      // Main Code - Verifies the form data, and inserts into      // the users table in the Database      if($HTTP_POST_VARS["submit"]=="Create User"){        $error = verify_data($HTTP_POST_VARS);        if ($error == "")          $success = "User inserted successfully";      }    ?> 

This code is run every time the page is loaded. First, it checks to see if the variable $Submit is equal to "Create User". If it is, the form data in the variable $HTTP_POST_VARS is passed to our verify_data() function, as defined above.

The variable $Submit will only equal "Create User" if the form has been submitted - submit is the name of the submit button, and "Create User" is the label for the button. If you have changed either of these, you will need to change them in the code here as well.

If the form has been submitted, it will run the verify_data () function, which if successful, will call the insert_data () function to insert the user details into the database.

The values of two variables, $error and $success, are now set in such a way that one has a value and one is empty. If an error is returned by the verify_data() function, then $error has a value, and $success is empty. If no errors are returned, $error will be empty, and $success will be set to "User inserted successfully".

We can place the two variables onto the page above the form using:

    <?php echo($error); ?>    <?php echo($success); ?> 

When a user first visits the page, nothing will be displayed, since both variables are empty. However, once the form has been submitted and the page is redisplayed, one of the two messages will be shown - either an error message or the success message.

Using the Page

We're now going to use this page, to create an "Admin"-level user. Upload the page to your server (along with the include file), and then load the page in your web browser. Enter your name, a username, and password. Select Admin from the status dropdown, and click Submit.

You should get a success message returned. If not, you will have to go back and check over your code. View the users table, and you should be able to see your new record. Look at the password field, and you will see it has been encrypted.

At the moment, anybody can access the page and create a new user. Obviously, this isn't something we want, so we will return to this page later, and add some more code, so that only "Admin"-level users can use the page.

The Login Page

The login page is a simple page that contains a table with a username and password field.

click to expand

The details for the form are as follows:

    <form name="form1" method="post" action="<?php echo($PHP_SELF) ?>">      <input name="username" type="text"  maxlength="20">      <input name="password" type="password"  maxlength="20">      <input type="submit" name="Submit" value="Login">    </form> 

Note that, like the create_user. php page, this page submits back to itself using the $PHP_SELF variable.

Layout the page as above using the template for the Dreamweaver Hotel site, and save the page as login.php in the admin folder.

Next we'll add the code that checks the login details against the database. Change into Code view, and scroll to the top of the page. On the first line, before the <HTML> tag, we include the PHP file dreamweaver_hotel_admin.php, which we created earlier.

    <?php include("../include/dreamweaver_hotel_admin.php"); ?> 

Again, we'll create two more pieces of PHP code to be added below this include file line.

check_login()

We'll first add a function to check the user details entered against those stored in the table.

    <?php    function check_login($formdata)    {      // This section queries the users table, and searches for      // the username and password that were supplied. If the      // user is not found, an error is returned. If the user      // details are correct the users status is returned.      // Set up MySQL Connection variables (change these to your own)      $dbhost = "localhost";      $dbuser = "username";      $dbpassword = "password";      $db = "databasename";      // Get Form Data      $form_data = trim_data($formdata);      $user = $form_data['username'];      $password = $form_data['password'];      // Connect to the mySQL Server      $mysql = mysql_connect($dbhost, $dbuser, $dbpassword);      if(!$mysql)      {        $error = "Cannot connect to Database Host";        return($error);      }      // Open the mySQL Database      $mysqldb = mysql_select_db($db);      if(!$mysqldb)      {        $error = "Cannot open Database";        return($error);      }      // Query Database with username and encrypted password      $myquery = "SELECT * FROM users WHERE username = '" . $user      $myquery .= "' AND password = '" . crypt($password,"DWMXPHP") . "'";      $result = mysql_query($myquery);      if (!$result)      {        $error = "Cannot run Query";        return($error);      }      // Check that we have a record returned      $numRows = mysql_num_rows($result);      if ($numRows < 1)      {        $error = "User name or password not recognised";        return($error);      }      // Get user status from returned record      $userRecord = mysql_fetch_array($result);      $status = $userRecord["status"];      return($status);    }    ?> 

The first section of this function sets up the database connection variables. Next, the form data array, which is passed to the function, is run though the trim_data() function we created earlier in the include file dreamweaver_hotel_admin.php.

The function then connects to the MySQL server, and opens the database. It then queries the database with the following SQL statement:

     SELECT * FROM users WHERE username = ' " . $user . " ' AND     password = ' " . crypt($password,"DWMXPHP") . " ' " 

Recall that when we create a user, we use the PHP crypt() function to encrypt the password with the key "DWMXPHP", and it was the encrypted password that we stored in the database.

As we mentioned earlier, crypt() is a one-way hash function - once the original data is encrypted it is lost. This doesn't cause us a problem, because encrypting data with the same key will produce the same result. By encrypting the provided password with the key "DWMXPHP", if the two passwords are the same, the encrypted user password will match the encrypted password stored in the database.

Next, we check the query has returned a record. If it hasn't, it means that the username or password are invalid, and we return this error.

If a record has been found, then the username and password provided were correct, and the user's status (either "Admin" or "Staff") is returned.

Using the Functions

The main code for the page is shown below:

    <?php    // This section is only run when the form has been submitted    if($HTTP_POST_VARS['Submit']=="Login")    {      session_start();      // Check whether the login details are correct, and put      // the user status into a session variable.      $statusCheck = check_login($HTTP_POST_VARS);      if ($statusCheck == "Admin" || $statusCheck == "Staff")      {        session_register("statusCheck");        header("Location: menu.php");      }    }    ?> 

This code is only run if the form has been submitted, in which case the variable $submit has the value "Login".

We then use the PHP function session_start() to begin a session, which we can use to store the user's status.

We next run the check_login() function we created earlier in this page, and pass it the form values, using the PHP variable $HTTP_POST_VARS. This function returns the user status (Admin or Staff) if their username and password are correct; otherwise an error message is returned. We store the result of the function in the variable $statusCheck.

Next, we check to see if $statusCheck contains "Admin" or "Staff", which means the login was successful. If so, we put the user's status into a session, which will allow their status to be saved and checked against as they change pages. Then we use the PHP header() function to redirect the user to the administration menu page, menu.php. Note, you can only use the PHP header() function if the header hasn't already been written by the browser. Keeping this code above the <HTML> tag ensures that the header() function can be used successfully, as the headers haven't been written yet.

If the check_login() function returns an error, then the session won't be set, and the page continues to load as normal.

You can now add the following code to your page, above the login form:

    <?php echo($statusCheck) ?> 

When the user first goes to the login page, this will show nothing since the $statusCheck variable will be empty. $statusCheck will only have a value once the user has submitted the login form, and the check_login() function has run. As this is not yet the case $statusCheck will contain the error message.

The Menu Page

The menu page is called menu.php. It is this page that users are redirected to once they have successfully logged in. For this example, it will contain three links, as shown in the screenshot below:

click to expand

  • View Bookings

    View Bookings should link to a page that will allow the user to view the various bookings that have been made. We will not actually be creating this page in this example.

  • Add New User (Manager Only)

    This link will point to the create_user.php page we created earlier.

  • Log Out

    This link takes the user back to the menu.php page, but with a query string parameter to tell the menu.php page that the user wants to log out. The href of the link is: menu.php?action=logout

Lay out a page with such links using the Dreamweaver Hotel template. Save it as menu.php in the admin folder.

The Menu PHP Code

Switch into Code view, and go to the top of the menu.php code, above the <HTML> tag.

The first segment of code we need to add is to start session support for the page. We then need to check the user has a session set, which can only happen if they have logged in correctly. If the user hasn't got a valid session, they are redirected back to the login page.

    <?php      session_start();      // If no session is set, redirect to login.php      if (!session_is_registered("statusCheck"))        header("Location: login.php");    ?> 

This segment of code needs to be inserted at the top of every page you wish to protect with the login system. Because the session is checked, it means that people who know the name of the page cannot bypass the protection by pointing the browser manually to that page.

We have one more segment of code to add to this page, and that is to log the user out. When the Log Out link is clicked, it sends the browser to the URL menu.php?action=logout. We modify the code block above, and add some code to handle the logout. Change the code above to read:

    <?php      session_start();      // If the user logs out, destroy their session      if($HTTP_GET_VARS["action"]=="logout"){        session_unregister("statusCheck");        session_destroy();      }      // If no session is set, redirect to login.php      if (!session_is_registered("statusCheck"))        header("Location: login.php");    ?> 

When the extra code we inserted above is run, it checks to see if the $action variable contains the value "logout", that is if the page is called through the Log Out link. It then deregisters and destroys the statusCheck session.

The original code is then run, and because a session is no longer set the user is redirected to the login.php page - effectively, they are logged out.

Create Users Page - Security

We now need to go back to the create users page, create_users.php. Open the page, and switch into Code view.

Earlier in this chapter, when we created this page, we didn't set any security, which meant that any user could log in and create a user. Obviously, we don't want this happening: we need to restrict ordinary staff (who have "Staff" status) from entering the page, but allow all managers (who have "Admin" status) to enter.

We're going to add some code to check the status value in the session variable statusCheck, and redirect the user back to the menu page if they only have "Staff" status. The page will load normally if the user has "Admin" status.

Go the top of the code, and you'll see the following line, which adds our extra functions stored in dreamweaver_hotel_admin.php to the code.

    <?php include("../include/dreamweaver_hotel_admin.php"); ?> 

Just after this line add the following block of code:

    <?php      session_start();      // Check the Users status, if not Admin level      // redirect back to the menu.php page      if ($HTTP_SESSION_VARS["statusCheck"] != "Admin")        header("Location: menu.php");    ?> 

This code can be placed on any page that needs protecting so that only "Admin" status users can use it. As the code uses the PHP header() function to redirect the user's browser, it is important that there is no "whitespace" (spaces or line breaks) sent to the browser before the code is executed. Make sure there are no spaces between your blocks of PHP code.

We've now completed the login section, so upload it to your server and you can see the pages in action.

Obviously, this is a very basic system, but it can be expanded on and used as a skeleton to make more complicated login systems, with more levels of authorization. This system can protect a large number of pages easily, simply by adding the relevant block of code to the top of the page, depending on which level of access is required.



Dreamweaver MX PHP Web Development
Dreamweaver Mx: Advanced Php Web Development
ISBN: 1904151191
EAN: 2147483647
Year: 2001
Pages: 88

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net