Pages

Banner 468

Monday, 25 April 2011

Building a Web Space Management System - 2

0 comments
 
Welcome to part 2 of this build. In part 1 we created a simple login form that authenticates users using server side validations and saw how to redirect the browser to the private area of the website. We also saw how to use sessions and session variables to check whether a user is logged in.

Till now, our valid username and password were hard-coded in our PHP script. We will now see how to store credentials on a MySql database and how we can query this database using PHP. We will build a simple registration page that will allow us to register new users, and modify the login page such that authentication is done against the database.

I have already created a database called "db_webspace" and a table within it (called "users") to store my user data.

1. The Regisration Page

We first need a page where users can register for our website.  To keep it simple we will only ask for a username, a password and an email address.   Here's what the form looks like:


We obviously want to validate the user input to make sure that the username is unique and that the passwords match.  Since I have already covered server-side validation in my previous post I will not go into too much detail, however I will discuss how to validate against the database.  Before that however, we need to register our first user and to do that we need a connection to our database:

<?php
   $conn = mysql_connect("localhost", "root", "mydbpassword");      
   if (!$conn) {
         die ("Unable to connect to database server".mysql_error());
      }
   //Connection successful;
?>

To connect to our database we first declare a variable ('$conn' in this case) and assign it the return value of the "mysql_connect" function.  This function takes the MySQL server name, username and password as arguments and opens a connection to that database.  It then returns a reference to that connection which we are storing in "$conn".  If the connection fails, "$conn" is set to FALSE.

I'm not very comfortable having my database password stored in plain text in the script.  In the real world I would probably store all connection properties within another file and encrypt them.  However, it must be said that if someone gains access to your php scripts, you're already in trouble no matter where and how you store your settings!

We now have a connection to our database.  Assuming that the user input is valid, here's how to register a new user:

$Result = mysql_select_db("db_webspace",$conn);
if (!$Result){
      $Out.="Unable to select DB: ".mysql_error()."
";
   }
else
   {
      $Uname = mysql_real_escape_string($_POST['txtUname']);
      $Pass  = mysql_real_escape_string($_POST['txtPassword']);
      $Conf  = mysql_real_escape_string($_POST['txtConfirm']);
      $Email = mysql_real_escape_string($_POST['txtEmail']); 
      
      //Validate...   
      
      //Register the user
   
      $SQL = "INSERT INTO users Values ('$Uname', '$Pass', '$Email')";   
      $Success = mysql_query($SQL, $conn);
      if ($Success)
         {// Show Thank-you message}   
      else 
         {// Show Error}
   } 

After successfully connecting to our database server, we use the 'mysql_select_db' function to select the actual database we want to work with which in our case is "db_webspace". In actual fact we are setting "db_webspace" as the currently active database for our connection ($conn) and every subsequent SQL query made using "$conn" will be executed on this database. Next, we use the "mysql_real_escape_string" function to sanitize user input. This is very important to make sure that the user input can be safely used in an SQL query. After performing some validations and assuming that our data is valid we construct an SQL statement to insert the values into the "users" table and execute the query using the 'mysql_query' function. Our user is now registered but the password is stored in plain text on the database. Here's a screenshot from "phpmyadmin" showing my registered users and their passwords in all their glory!


To fix this I will use the SHA1 hashing algorithm to hash the user's password before storing it into the database:

...
//Hash the password 
$Pass = sha1($Pass);   
$SQL = "INSERT INTO users Values ('$Uname', '$Pass', '$Email')";
...

Here's what the hashed password looks like for the 'secadmin' user:


We now have a way of registering our users and storing their passwords securely on our database.

2. Authenticating against the Database


Let's turn our attention now back to the login page and add the necessary code to authenticate our newly registered users against the database:

...
$conn = mysql_connect("localhost", "root", "mydbpassword");      
if (!$conn){
   die ("Unable to connect to database server".mysql_error());
}
$Result = mysql_select_db("db_webspace",$conn);
if (!$Result){
  //Show error and terminate script execution
}
else {
   // Sanitize user input      }
   $User = mysql_real_escape_string($_POST['txtUname']);
   $Pass = mysql_real_escape_string($_POST['txtPassword']);
   
   //Hash the password to compare it to hash in db
   $Pass = sha1($Pass);

   $Sql = "Select Count(*) As myCount 
           From   users 
           Where  userid='$User' 
           And password='$Pass'";  
          
   $Result = mysql_query($Sql, $conn);
   $Row    = mysql_fetch_array($Result);
   if ($Row['myCount'] > 0){
      //Set session variables and redirect to private page      
   } 
   else{
      //Incorrect username or password
   }
}
...

Just like our registration page, we first need to create a connection to and select our database. Next the user input is sanitized and the password is hashed so that it can be compared to the hashed value in the database.  Finally an SQL select statement is executed to return the number of matching records for our username and password combination.  Unlikely as it may seem, the next part is what confused me the most: how to read the result back from the query.  If the query is successful, "mysql_query" returns a "resource" ($Result) which I   then passed to the "mysql_fetch_array" function which in turn returns an array to the fetched row, which in this case is made up of just one column "myCount" (an alias for the count(*) sql expression).  I can then access the value of "myCount" through this associative array and grant/deny access accordingly.


What next?

With the authentication mechanism out of the way I will shift my focus on the application functionality itself: uploading and managing files, quota management and eMail notifications.

I must say however that even at this relatively early stage, the code is starting to look untidy and not as modular as I would like so I've been looking into the Model View Controller (MVC) pattern for PHP. Even from the outset it is clear that MVC would make the code much more maintainable by achieving a clear separation between application logic and the presentation layer (HTML). Also, using Object Oriented Principles (OOP) will add further modularity (separation of concerns) of the code. The downside to MVC is that it takes some getting used to and unless using an existing framework, it takes some effort to implement from scratch. Having said that, I have found some useful resources online to get me started so I might implement MVC on this project in time for my next post.
Readmore...
Wednesday, 13 April 2011

Building a Web space Management System 1

0 comments
 
Hello again. As I explained way back in my very first post I am a Middlesex University student studying for a degree in Internet Application Development. The purpose of this blog has been to share my thoughts and experiences on the practical work I've been carrying out during this course.

During my next few posts, I will be building a small Web space management System using PHP.

Task Definition

The aim of this task is to 'write a Web space management system suitable for handling Web site content of various types. It should allow users to add and organise files to a personal Web area which is secured by a password.'  The 'program' should support the following features:
  • Passwords are to be stored on a MySQL database
  • Authenticated users should be able to craete/upload/delete files and directories
  • Users should only be able to access their own space
  • Space quotas (limits)
We have our requirements, so let's get started!

1. The Login Form

The first step is to create a login form for our users. Later on in the series (when tackling MySQL connections) I will create a proper user registration form, but at this stage I will assume that I already have some registered users.  The login form accepts a username and a password (obviously) and will support a "remember me" feature. I've used HTML & CSS techniques discussed in my earlier posts to style the form. 

Here's what it looks like:


I've also added some simple javascript validations to prevent the form from being submitted if either the username or the password is left blank. However, it is always a good idea to duplicate such validations on the server as well since we have no way of knowing whether javascript is enabled on the client's browser!
I want to place these server-side validations on the login page itself so I have set the 'action' attribute of the login form to request itself. I don’t want to hard-code the name of the page so I will be using PHP to set the value of the “action” attribute of our form. Here’s one way of doing this:

<form action="<?php echo $_SERVER['SCRIPT_FILENAME'] ?>" method="post" id= ... >

We could also use ‘PHP_SELF’ instead of ‘SCRIPT_FILENAME’ however, as explained by Luke Visinoni in this article, this variable 'cannot be trusted' as it is vulnerable to cross-site scripting attacks. Using ‘SCRIPT_FILENAME’ is a safer option.

Next we add the PHP validations just below the "body" tag:

<?php
   $ErrMsg = "";  
   //Execute only if the page has been posted back (not first time load)
   If ($_SERVER['REQUEST_METHOD'] == 'POST')
   {
      //Validate user input: username and password must not be blank  
      if ($_POST['txtUname'] != "" && $_POST['txtPassword'] != "")
      {
        //Authenticate the user
      }
      else 
      {
        $ErrMsg = "Please enter a username and password";  
      }
   }
?>

Since we are posting to the same page, we want to prevent validations and subsequent authentication logic from executing when the page is loaded for the first time. At line 5, the script checks the request method of the page and will only execute the rest if it is set to ‘POST’. Assuming that the client will use a GET method when requesting the page for the first time this method will work fine. There are other techniques which could be used but for the sake of simplicity we’ll stick to this method. I must say however that at this stage I have yet to find a ‘fool proof’ method for doing this check as all the ones I came across have some kind of drawback. I guess avoiding posting to the same page or better still use an MVC framework would be a better solution but for now checking the request method will do nicely.

2. Server-Side Validation & Authentication

The previous code listing includes the first validation I want to add to the form, i.e. making sure that both the username and password are not left blank. Looking at line 8, ‘$_POST’ is a global associative array of variables which are passed to the script whenever a page is posted. It will contain the values of all the input fields in the submitted form. In our case, ‘txtUsername’ and ‘txtPassword’ are the names of the text boxes (HTML input type=text) for the username and password respectively. The names of these fields are set as keys in the $_POST associative array through which we can get to the actual values (See my previous post for more information on associative arrays). If either the username or password is left blank, the script sets the ‘$ErrMsg’ variable to the appropriate error message which is then ‘echo’ed to the user further down the page:


As I mentioned earlier, I am assuming that I already have some registered users. By that I mean that I have hard-coded a username and password in the script to represent values returned from a database. I will come back to this script later on in the series when I set up a proper registration page and store user accounts on a MySQL database. At this stage I wanted to focus on how to redirect authenticated users to the ‘private’ area and how we can use cookies/sessions to ‘remember’ a user. So, building on the previous script:

…
//Validate user input: username and password must not be blank  
if ($_POST['txtUname'] != "" && $_POST['txtPassword'] != "")
{
   //Authenticate the user
   define ("User", 'guest');
   define ("Pass" , 'letmein');
   if($_POST['txtUname']==User And $_POST['txtPassword']==Pass)
   {
      header("Location: http://localhost/PHPLabs/private.php");
   }   
   else 
   {
      $ErrMsg = 'Incorrect username or password';
   } 
}
else 
… 

After checking that the username and password are valid (against my hard-coded values) the ‘header’ function is called which sends a raw HTTP header to the browser causing the redirection to the selected page (private.php in this case). Pretty simple, however there’s a catch or rather two of them. First, any code after the header function will still be executed! In our case this is not that big of a problem as the script is quite small, however larger scripts would take longer to execute and consume more resources. Depending on how popular your site is and how many hits/requests it gets, these ‘wasted’ resources could have a negative effect on performance. To avoid this problem we can simply call to the ‘die()’ function after the redirection which will prevent the rest of the script from being executed. Secondly, the ‘header()’ function must be called before any kind of output is sent to the browser, including HTML tags, echo and print functions, otherwise it will not work. However you can use PHP output buffering to avoid this:

//Authenticate the user
define ("User", 'guest');
define ("Pass" , 'letmein');
if($_POST['txtUname']==User And $_POST['txtPassword']==Pass)
{
   ob_start();
   echo “Testing output buffering”;
   header("Location: http://localhost/PHPLabs/private.php");
   ob_flush();     
}   
else 
{
   $ErrMsg = 'Incorrect username or password';
} 
… 

The ‘ob_start()’ function turns on output buffering which will prevent the script from sending any output – except for headers – until ‘ob_flush()’ is called, so in this case no error is reported.

3. Using Sessions

Up to this point we have successfully redirected the user to the ‘private.php’ page after entering a valid username and password. However, ‘private.php’ still needs to verify that the user has been authenticated; otherwise all requests made to the page would be accepted! We need a way of persisting the ‘authenticated’ state until the user logs out or closes the browser. Here’s where sessions can help. Sessions are a combination of a client-side cookie and a server-side cookie where the former only contains a reference to the latter. For this reason, sessions are more secure than traditional cookies since the client has no means of changing important data stored within the cookie. Take a shopping cart for instance. If the shopping cart data was stored in a cookie on the client, the user could easily change the price (for example) of a given item before checking-out! Using cookies in this scenario is bad enough, placing something such as the price within that cookie is just asking for trouble.

Back to our scenario, we want to store a flag indicating that the user has been authenticated within a session variable such that it is accessible by every page in our private or member’s area. Here’s how it’s done:

session_start();
…
//Authenticate the user
define ("User", 'guest');
define ("Pass" , 'letmein');
if($_POST['txtUname']==User And $_POST['txtPassword']==Pass)
{
   $_SESSION['loggedin'] = 1;
   $_SESSION['userid'] = $_POST[‘txtUname’];
   header("Location: http://localhost/PHPLabs/private.php");
   die()
}   
else 
{
   $ErrMsg = 'Incorrect username or password';
} 
… 

We first need to place a call to ‘session_start()’ at the beginning of our PHP script (line 1). This will inform PHP that we intent to use sessions and to expect the use of session variables. Next, we use two session variables to store the flag indicating that the user has been authenticated as well as the username itself. As you can see, session variables in PHP are stored in an associative array called $_SESSION.

We now want to make sure that the private.php page checks for these session variables. This will ensure that when requesting the private page directly the client is redirected to the login page for authentication:

session_start();

if (isset($_SESSION['loggedin']))
{
   echo "Welcome ".$_SESSION['userid']; 
}
else 
{
   header('Location: http://localhost/PHPLabs/Forms.php');
   die();
}

Once again we should start the script by calling the session_start() function to gain access to the session variables which are then checked. If the ‘loggedin’ variable is set, the user is granted with a welcome message but otherwise redirected to the login page.

Finally, I will add a ‘logout’ button that will end the user’s session gracefully. The button simply calls the logout.php script which closes the session and redirects the client to the login page:

<?php
   //logout.php;
   session_start();
   session_unset();
   header("Location: http://localhost/PHPLabs/login.php");
   die();
?>

It might look odd that the scripts calls the session_start() function just before calling session_unset(), however it will not work otherwise. Remember that session_start() not only checks for an existing session and creates one if it finds none but it also gives the script access to the session variables. In essence, session_unset() would have nothing to unset unless session_start() is called beforehand! A bit confusing at first bit it does make sense when you think about it.

Wrapping up


That's it for this post.  We have seen how to create a simple login form and how to add server side validations to validate user input and authenticate the user.  We've also seen how we can redirect the client to the private area after authentication and how to use sessions to our advantage.  I haven't implemented the "remember me" check box yet, but I will be doing so when discussing cookies and personalisation later on in the series.

Overall, this exercise is helping me gain a clearer picture of  what PHP is all about.  In it's raw state its much more low level than what I'm used to (ASP.Net) but I've found it to be simple to learn, easy to use and fast performing. Also, the sheer amount of information about PHP on the Web can be quite overwhelming and sometimes contradictory.  I've found that - just like seeking medical advice - it's best to get a second opinion before embracing a concept.  As stated in my previous post, PHP is easy to learn but it is even easier to learn coding it badly.

My next post will focus on how to connect our PHP pages to a MySQL database and how to authenticate our users properly against that database.
Readmore...
Sunday, 10 April 2011
0 comments
 

Server-Side Languages 2 - Basic PHP


In my last post, we looked at how to use XAMPP to set up an Apache web-server that includes MySql and PHP.

This post will focus on the PHP server-side language itself and how we can use it to generate dynamic web pages.

What is PHP?


PHP is a free, platform independent scripting language originally developed way back in 1995 specifically for creating dynamic web pages. PHP originally stood for “Personal Home Page”, however it is now widely accepted that PHP is a recursive acronym standing for “PHP: Hypertext Preprocessor”. Whatever the meaning, PHP has grown into one of the most popular scripting languages in use today.

As with any programming language, the best way to learn/explain how it works is through practical examples. During this post I will introduce basic PHP syntax and how to use variables, arrays and loops to create (step-by-step) a simple page that dynamically displays a list of usernames and passwords.

Step 1 – “Hello World”


The following snippet shows a simple HTML page with some embedded PHP code between the '<?php' and '?>' tags.  Any text between these tags will be interpreted by PHP on the web server before sending the page to the client (web browser).  In this case,  we are using the 'print' PHP construct to place "Hello World!" between the <h1> tags.  Furthermore we are using a double forward slash (//) to add a single line comment to the script.

<html>
      </head></head>
      <body>
         <h1>
            <?php
               //Display "Hello World!" between h1 tags
               print "Hello World!";
            ?>
         <h1>
      </body>
   </html>

We could also use 'echo' instead of 'print' to produce the same effect. So what's the difference? Basically both 'echo' and 'print' are PHP constructs that output text to the screen but the difference lies in how they are structured and not what they do. Basically the 'print' construct returns a value, just like a function, while 'echo' does not. What this means is that when looping through an extended amount of iterations, 'echo' performs faster than 'print'.

Step 2 - Variables

PHP is a loosly-typed language meaning that we do not need to specify a datatype when declaring variables.  In the following code snippet, I will create two variables to store values for a username and a password and use the echo construct to display these values to the user:

<html>
   <head></head>
   <body>
      <?php
         /*
           Declare variables.  
           All variables in PHP start with a '$' sign
         */
         $Uname = 'guest';
         $Pword = 'guest123';            
            
         echo "Username: ".$Uname."<br>";
         echo "Password: ".$Pword;

      ?>
   </body>
</html>

Pretty straight forward so far. One thing of note however is how the value of a variable is being concatenated to the rest of the string. In PHP the concatenation operator is the '.' rather than the more commonly used '+'.

Before going onto arrays I would like to demonstrate how to replicate the above example using constants rather than variables. Constants are 'special' variables whose values cannot change, or remain constant (hence the name). Here's how the above example would look like when using constants:

<html>
   <head></head>
   <body>
      <?php
         /*
            Define constants.  
            The value of a constant cannot be changed
         */
         define ('Uname', 'guest');
         define ('Pword', 'guest123');        
         
         echo "Username: ".Uname."<br>";
         echo "Password: ".Pword;
      ?>
   </body>
</html>

Constants are defined using the 'define()' function, passing the name of the constant and its value as parameters. Unlike variables, names of constants must start with a letter or an underscore and are - by default - case sensitive (like the rest of the language for that matter).

Step 3 - Arrays


In PHP we can use three kinds of arrays:

  • Numeric Arrays
  • Associative Arrays
  • Multidimensional Arrays

I have already discussed numeric arrays in detail in previous posts so I will focus on Associative Arrays instead (We'll tackle multidimensional arrays in my next post).

An associative array is basically a collection of key-value pairs whereby we can retrieve a specific value based on a string key rather than a numerical index. Associative arrays are used extensively in PHP: $_REQUEST, $_SESSION and $_COOKIE are all examples of pre-defined associative array variables. $_COOKIE for instance is an associative array that stores variables passed to the script through HTTP cookies. We will see these (and more) of these pre-defined variables in action in the next post, but for now we will see how we can define and use our own associative arrays.

As mentioned at the beginning of this post, I want to create a script that displays a table of usernames and passwords to the user. In the next code listing, I will define an associative array to store my username and password 'pairs':

<html>
   <head></head>
   <body>
      <?php
         // Define the associative array
         $users = array("admin"=>"admin123",
                        "user1"=>"letmein",
                        "guest"=>"guest100,"
                        "Wimpy"=>"hamburgers");
      ?>
      <h3>User List</h3>
      <table border="1">
         <tr>
            <th>Username</th><th>Password</th>
         </tr>
         <tr>
            <?php 
               echo "<td>admin</td>";
               echo "<td>".$users['admin']."</td>";
            ?>
         </tr>
         <tr>
            <?php 
               echo "<td>user1</td>";
               echo "<td>".$users['user1']."</td>";
            ?>
         </tr>
         <tr>
            <?php 
               echo "<td>guest</td>";
               echo "<td>".$users['guest']."</td>";
            ?>
         </tr>
         <tr>
            <?php 
               echo "<td>Wimpy</td>";
               echo "<td>".$users['Wimpy']."</td>";
            ?>
         </tr>
       </table>
   </body>
</html>

Best practices apart, the above example demonstrates how to define an associative array (line6) where the key-value pairs are the usernames and passwords respectively. Simple echo statements are used to display the users as an HTML table. This is obviously not the best way to do this. One of the advantages of arrays is that they allow us to iterate through their values, which brings us to the final topic of this post:

Step 4 - Looping Through Associative Arrays


As we have seen, associative arrays are based on string values (keys) rather than numeric indices which means that we cannot use a counter in a for loop to iterate through the array. We can however use the foreach loop or the each() and list() constructs instead.

Method 1 - The Foreach Loop

<?php
   // Define the associative array
   $users = array("admin"=>"admin123",
                  "user1"=>"letmein",
                  "guest"=>"guest100",
                  "Wimpy"=>"hamburgers");
?>

<h3>Method 1 - Simple Foreach</h3>
<table border="1">
   <tr><th>Username</th><th>Password</th></tr>
   <?php  
      foreach($users as $username => $password)   
         echo "<tr><td>".$username."</td>";
         echo "<td>".$password."</td></tr>";
   ?>

</table>
In this method, we use a simple foreach loop to iterate through each username and password pair. During each iteration, the values of the current element in the array copied into the '$username' and '$password' variables respectively which are then used in the echo statements further down.
Method 2 - Using the 'each()' construct
We can also use the each() construct within a while loop to iterate through the array. Each() will return the current key and value pair as a four element array which allows us to get the value either through the key or through a numeric index. Using our $users array as an example, the first time 'each($users)' is called, the returned array, say $user, would look like this:
$user
(
[0] = 'admin'
[key] = 'admin'
[1] = 'admin123'
[value] = 'admin123'
)

Here's what the code looks like when using 'each()':

<?php
<h3>Method 2 - Using the each() construct </h3>

<table border="1">
   <tr><th>Username/th><th>Password</th></tr>
   <?php
      while($user = each($users))
      {
         echo "<tr><td>".$user['key']."</td>";
         echo "<td>".$user['value']."</td></tr>";
      }
   ?>

</table>
Since the 'each()' construct sets the array cursor to the next element in the array (or beyond), you must use the 'reset()' function to use the array with 'each()' again.
There is however a more common way of using 'each()' which also easier to understand:

Method 3 - Using 'each()' and 'list()'

while (list($uName, $pass) = each($users))

The above statement executes the 'each()' function to get the current key-value pair of the $users array and makes the next element current. The 'list()' function takes the [0] and [1] elements of the array returned by 'each()' and places the values into variables named '$uName' and $pass. We can then 'echo' the values of these variables as usual.

Conclusion

During this rather lengthy post we have taken a look at some baisc PHP and how we can use this popular scripting language to generate some dynamic content on the server. Being an ASP.net developer myself, this was my first experience in working with PHP. I must admit that although PHP is easy to learn, the lax nature of the language allows for some really bad-practice coding. The real challenge in my opinion is not learning the PHP syntax itself, but rather learning how to use it well in a disciplined and ordered manner. Raw PHP reminds me of the old ASP days where the notion of separating code from markup was something we fantasized about. Full-blown ASP web applications were a nightmare to maintain due to the way code and markup was intertwined in true spaghetti fashion.
There are however patterns and frameworks that help mitigate this problem and I will definitely look into them in the near future.
In my next post, I will be building a simple login page and use PHP to 'authenticate' users and we will also look at how we can use and manage sessions and cookies.
Readmore...