miercuri, 21 noiembrie 2007

User Authentication With Image Verification

User Authentication With Image Verification

In some cases you may want your loging form to be able to prevent automatic login by a robot ( script ). To achieve this we can create a login form which displays an image showing random numbers. The login form will have an extra input field to enter the values shown.
Take a look at the login form. The numbers shown there will change everytime you refresh the page. Go ahead and try refreshing that page you will see the numbers always change.
Before working on the login form we must take care of the script that create the verification image first. Here is the code :
Example : image-verification/randomImage.phpSource : image-verification/randomImage.phps
// generate 5 digit random number$rand = rand(10000, 99999);
// create the hash for the random number and put it in the session$_SESSION['image_random_value'] = md5($rand);
// create the image$image = imagecreate(60, 30);
// use white as the background image$bgColor = imagecolorallocate ($image, 255, 255, 255);
// the text color is black$textColor = imagecolorallocate ($image, 0, 0, 0);
// write the random numberimagestring ($image, 5, 5, 8, $rand, $textColor); // send several headers to make sure the image is not cached // taken directly from the PHP Manual// Date in the past header("Expires: Mon, 26 Jul 1997 05:00:00 GMT");
// always modified header("Last-Modified: " . gmdate("D, d M Y H:i:s") . " GMT");
// HTTP/1.1 header("Cache-Control: no-store, no-cache, must-revalidate"); header("Cache-Control: post-check=0, pre-check=0", false);
// HTTP/1.0 header("Pragma: no-cache");
// send the content type header so the image is displayed properlyheader('Content-type: image/jpeg');
// send the image to the browserimagejpeg($image);
// destroy the image to free up the memoryimagedestroy($image);?>
To create a five digit random number we use rand() function and specify that the random number must be between 10000 and 99999. We put the hash value of this random number in the session. This hash value will be used by the login script to check if the entered number is correct.
Next we create a small image, 60 x 30 pixels, using imagecreate(). We set the background color to white ( RGB = 255, 255, 255 ) using imagecolorallocate() function. Note that the first call to imagecolorallocate() will always set the background color for the image. Then we set the text color as black ( RGB = 0, 0, 0 ). Feel free to change the color text to your liking.
To print the random number to the image we use the function imagestring(). In the script above we call this function like this : imagestring ($image, 5, 5, 8, $rand, $textColor);
The first argument passed to this function is the image handler ( $image ). The second one ( 5 ) is the font. You can choose from one to five where one is the smallest font. The third and fourth parameter is the horizontal and vertical coordinate where we will print the image. The top left corner is defined as 0, 0. The last one is the text color which is black as mentioned earlier.
After we got the image ready we can now send it to the browser. But before doing that we must set several headers to make sure that the image is not cached. If the image is cached then the login form will show the same image even if you refresh it. That will cause a problem since the random number is always different.
Finally after everything is set we send the image to the browser using imagejpeg() and to free the memory we use imagedestroy().

The Login Form
The login form is pretty much the same but only have extra field to enter the displayed number.
Example : image-verification/login.phpSource : image-verification/login.phps
Basic Login

User Id
Enter Number

To check if the login information is correct we first check if the entered number is the same one as displayed in the image. To do this we check the hash of the entered number and see if it match the one saved in the session. If the number don't match we just set an error message.
If the number do match we continue checking the given user id and password just like the previous example. If the userid and password combination is correct we set $_SESSION['image_is_logged_in'] to true and move on to the main page
Example : image-verification/login.phpSource : image-verification/login.phps
$errorMessage = '';if (isset($_POST['txtUserId']) && isset($_POST['txtPassword'])) { // first check if the number submitted is correct $number = $_POST['txtNumber']; if (md5($number) == $_SESSION['image_random_value']) { include 'library/config.php'; include 'library/opendb.php'; $userId = $_POST['txtUserId']; $password = $_POST['txtPassword']; // check if the user id and password combination exist $sql = "SELECT user_id FROM tbl_auth_user WHERE user_id = '$userId' AND user_password = PASSWORD('$password')"; $result = mysql_query($sql) or die('Query failed. ' . mysql_error()); if (mysql_num_rows($result) == 1) { // the user id and password match, // set the session $_SESSION['image_is_logged_in'] = true;
// remove the random value from session $_SESSION['image_random_value'] = ''; // after login we move to the main page header('Location: main.php'); exit; } else { $errorMessage = 'Sorry, wrong user id / password'; } include 'library/closedb.php'; } else { $errorMessage = 'Sorry, wrong number. Please try again'; } }?>
We don't need to discuss about main.php and logout.php since they are the same as previous example except the session name is now called $_SESSION['image_is_logged_in']. So instead of working on those two files let's move on to a more interesting stuff...

Improving The Verification Image
We can improve the verification image in at least two ways. They are :
Using alphanumeric characters as the verification code instead of numbers
Using backgound images
For the first improvement the only thing we need to change is the way we generate the code. Take a look at the code below
Example : image-verification/randomImage2.phpSource : image-verification/randomImage2.phps
// generate the verication code $rand = substr(str_shuffle($alphanum), 0, 5);
// ... no changes after this point?>
We start by defining the characters that we want to use in the verification code. For this example we use upper case alphabet plus numbers. The code is generated using the combination of str_shuffle() and substr() function. Using str_shuffle() we jumble all the characters in $aplhanum and then using substr() we take just the first five characters. The result will look something like "D79ZG". Just run the example and see it for yourself.
The second improvement is by using background images. Maybe you already know this but there are software/scripts that can extract the characters displayed as images. And if the verification image only use plain background color identifying the characters wil be quite easy.
For this reason we will make the verification code displayed on a background image. In this tutorial we will only use four different background images. You can add as many background images as you want in your own code. Here are the background images :
background image #1 :
background image #2 :
background image #3 :
background image #4 :
Note : When you want to create a background image make sure the code will still be readable on them. For instance it's quite hard ( at least for me ) to recognize the code when the code is displayed on image #1 and image #4. Go take a look if you don't believe me.
Here is the code for this second improvement
Example : image-verification/randomImage3.phpSource : image-verification/randomImage3.phps
// generate the verication code $rand = substr(str_shuffle($alphanum), 0, 5);
// choose one of four background images$bgNum = rand(1, 4);$image = imagecreatefromjpeg("background$bgNum.jpg");
$textColor = imagecolorallocate ($image, 0, 0, 0);
// write the code on the background imageimagestring ($image, 5, 5, 8, $rand, $textColor);
// ... no changes after this point?>
After making the verification code we randomly pick one background image. Then we create an image object from the chosen background using imagecreatefromjpeg() and draw the code on the background. The rest of the code is the same as randomImage1.php and randomImage2.php so no need to explain it here.
Okay that is it. The three method of user authentication. Just pick one that fit your application.

Niciun comentariu: