Article
Toughen Forms' Security with an Image
Page: 1 2
We better create that wrapper quickly! It's imaginatively called Create:
function Create($sFilename = '') {
// check for existence of GD GIF library
if (!function_exists('imagegif')) {
return false;
}
$this->DrawLines();
$this->GenerateCode();
$this->DrawCharacters();
// write out image to file or browser
if ($sFilename != '') {
// write stream to file
imagegif($this->oImage, $sFilename);
} else {
// tell browser that data is gif
header('Content-type: image/gif');
// write stream to browser
imagegif($this->oImage);
}
// free memory used in creating image
imagedestroy($this->oImage);
return true;
}
It starts by checking for existence of the imagegif function, and therefore, by implication, the GD library. If it doesn't find it, the function exits and returns straight away -- after all, there's no point continuing if the image generation functions don't exist.
Assuming the function gets past this check safely, DrawLines, GenerateCode and DrawCharacters are called to carry out those all-important functions.
Next, the image is created with imagegif, and saved to a file, or, in the case of our example, written to the user's browser. The final step frees memory used by the process.
We've only got one more tiny method to flesh out, and our class will be complete! GetCode simply returns a textual representation of the random characters generated and, as mentioned above, allows us to compare those characters with user-entered input. Here it is, short and sweet:
function GetCode() {
return $this->sCode;
}
Putting the Class to Use
It's time to implement this solution in a real application. We're going to create a simple login form that prompts users to enter their usernames and passwords, but additionally displays our security image and asks them to type the characters they see. We will assign a textual representation of the code displayed by the image to a PHP session variable. When the users submit the form, we'll compare the code they entered with the characters stored in our session variable. If they match, we'll show the users a suitably congratulatory message. If the character strings don't match, we'll let the users know, and provide them with a link to go back and try again. For the purposes of this example, we won't worry about what they enter in the username and password fields of our form.
And all the code that we'll discuss in this section is included in this downloadable code archive.
Creating a Wrapper Page
First, we'll create a page (security-image.php, which can be found in the code archive) that will call the new class and pass any required parameters.
This page starts by including the file (security-image.inc.php, which is contained in the code archive) that contains the SecurityImage class. Next, we call session_start. Any PHP page that makes use of sessions needs to call this before any other output is sent to the browser. It creates a new session, or resumes an existing one.
We then pick up any GET variables passed to the page, and assign them to relevant variables. If a GET variable doesn't exist for a specific option variable, we assign a default. We then call the SecurityImage constructor, passing our preferences, to create a new instance of the class.
Next, the Create method is called. If this returns successfully, we assign the corresponding textual code of the generated image to our session variable. If it's not successful, we return a suitable error message instead:
<?php
// include security image class
require('includes/security-image.inc.php');
// start PHP session
session_start();
// get parameters
isset($_GET['width']) ? $iWidth = (int)$_GET['width'] : $iWidth = 150;
isset($_GET['height']) ? $iHeight = (int)$_GET['height'] : $iHeight = 30;
// create new image
$oSecurityImage = new SecurityImage($iWidth, $iHeight);
if ($oSecurityImage->Create()) {
// assign corresponding code to session variable
// for checking against user entered value
$_SESSION['code'] = $oSecurityImage->GetCode();
} else {
echo 'Image GIF library is not installed.';
}
?>
The page, which outputs an image direct to the browser, will be called from an HTML image tag in our next page, which displays our login form.
Creating the Login Page
The login page submits to itself and serves the dual purpose of displaying the form and the two possible result messages.
As an added bonus, our form is coded semantically using CSS. There's not a table or break tag in sight!
<?php
// start PHP session
session_start();
?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
<head>
<title>Security Image Test</title>
<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1" />
<style type="text/css">
form { width: 18em; }
fieldset { display: block; float: left; }
legend { font-size: 1.2em; font-weight: bold; color: #000; }
#security img { float: right; border: 1px solid #000; }
label, input, #security img { margin: 5px 0; }
input, #login { float: right; }
label, #login { clear: both; }
label { float: left; width: 7em; }
#login { margin-top: 5px; }
</style>
</head>
<body>
<?php
// check for posted form
if (isset($_POST['login'])) {
// see if the code the user typed matched the generated code
if (!empty($_SESSION['code']) && strtoupper($_POST['code']) == $_SESSION['code']) {
unset($_SESSION['code']);
echo 'Congratulations, you entered the correct code.';
} else {
echo 'You have entered the wrong code. Please <a href="index.php">try again</a>.';
}
} else {
?>
<form method="post" action="index.php">
<fieldset>
<legend>Login</legend>
<label for="username">Username:</label><input type="text" name="username" id="username" value="" />
<label for="password">Password:</label><input type="password" name="password" id="password" value="" />
<div id="security"><img src="security-image.php?width=144" width="144" height="30" alt="Security Image" /></div>
<label for="code">Security Image:</label><input type="text" name="code" id="code" value="" />
<input type="submit" name="login" id="login" value="Login" />
</fieldset>
</form>
<?php
}
?>
</body>
</html>
The page starts by calling the session_start function.
Next the HTML header and the CSS that defines the visual representation of the form are written; a check for form submission follows. If the form has been submitted, the user-entered code is checked against the saved version, and the appropriate message is displayed. If the form hasn't been submitted, the form is displayed. As we can't be sure that our user will enter the code using only upper case characters, strtoupper is used to convert their input before the comparison is made.
The Finished Form
You can see a screen shot of our finished form complete with security image below:

With that, we've completed our Security Image implementation! Take a well-earned coffee break and ponder on the possibilities for integrating this example into your forms.
You can find out more about the PHP GD functions at PHP.net.