newb.org.uk >> Tutorials >> Tutorial: Simple CAPTCHA

Greetings again, internet denizens. In this tutorial, we will be learning how to make a simple(ish) CAPTCHA in PHP, using the GD library to output images. We will also explore the use and creation of custom functions, as well as the inclusion of code from external files.

  • Things you will require:
  • A web-server running PHP
  • A text editor ( I recommend Notepad++  )
  • Some previous HTML/XHTML knowledge
  • A smattering of PHP knowledge
  • An image creation application / stock image (for the background)
  • A nice looking .ttf format font file
  • About 30 minutes

Follow this link to see the CAPTCHA in action.

 

Note: Just after I started writing this tutorial, Jimmy K, a friend of mine from END[SEVEN] wrote a simpler and perhaps more intuitive guide to writing a CAPTCHA, that is available here. If you are looking for a simpler solution, check out his guide.

Gathering Resources

The first things that you need to get together, obviously, are the resources required for the project. In this case, this involves a TrueType (.ttf) font file, and a suitable background image for the CAPTCHA to use. You can use any font and any background image, but make sure that when the font is layered over the image it is readable to the human eye.

In this tutorial, we will be using the font "Verdana," as this comes by default on most operating systems and is therefore easy to locate. The background image in use will, in fact, be the same pretty header image that appears at the top of this page (Download Here).

Getting Started

I recommend creating a new folder named 'captcha' or something similar in order to hold the project files, in order to keep them separate from other files and sections on your site. For the purpose of this tutorial, I will assume that you are saving all of your files within the 'captcha' folder - however you should obviously change the folder in the source if you are using a different directory.

Upload your background image file, and of course .ttf font file to the appropriate directory on your server, and then move onto the PHP code presented below.

Source Code (Download)

index.php

<?php
    session_start
();        // Initialize the session to save our captcha text
    
$_SESSION['capTxt']    =    md5 microtime() ); // Create a 'random' string
    
$_SESSION['capTxt']    =    substr $_SESSION['capTxt'], 0);    // Shorten it
    
    // This is all that really needs to be done to initialize the captcha, get some HTML on the go
    
?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en-gb" lang="en-gb" >
    <head>
        <title>Captcha</title>
        <style type="text/css">
            body{ font-family:Verdana;font-size:11px;margin:15px; }
            iframe{border:0px;padding:0px;margin:0px;}
        </style>
    </head>
    <body>
        <img src="captcha.php" alt="Captcha" /><br /><br />
        <form action="check.php" method="POST" target="testFrame">
            <label for="cap">Enter code:</label>
            <input type="text" name="cap" />
            <input type="submit" value="Submit" /><br />
            Code is not case sensitive<br /><br />
        </form>
        <iframe src="check.php" name="testFrame"> </iframe>
    </body>
</html>

captcha.php

<?php
    
// CAPTCHA by newb 2009
    // http://www.newb.org.uk/
    
    
session_start();    // Initialize session to retrieve the text
    
    // This is a custom function definition, which we use to output the image itself.
    
function makeCaptcha($text,$bg,$width,$height,$font,$fontSize){
        
/*
            Function to generate a simple CAPTCHA
            Usage: makeCaptcha ( text, background image, width, height, font-file, font-size );
        */
        
header("Content-type: image/png");    // Make sure an image is being output
        
        
$img    imagecreatetruecolor($width,$height);    // Create an empty image at our desired size
        
$im     imagecreatefromjpeg($bg);                // Open the background image
        
        
imagecopyresized $img$im0000$width$height$width$height);
                    
// Copy a portion of the background to our new image
        
        
$size    =    $fontSize;                            // Set font-size
        
$x        =    ($width/2)-$fontSize*5;                // Set left-spacing
        
$y        =    ($height/2)+$size/1.6;                // Set vertical spacing (should be around central)
        
$white    =    imagecolorexact  $img255255255  );    // Set up some colours...    White
        
$black    =    imagecolorexact  $img0,);            //                            Black
        
$text    =    strtoupper($text);                    // UPPERCASE any letters in the text
        
foreach ( str_split($text) as $char){
            
// This allows us to process each character of the string individually
            
$angle    =    rand(-20,20);        // Randomly calculate the angle of each character
            
$siz    =    $size+rand(-2,6);    // Same for the size
            
imagefttext $img$siz$angle$x$y$white$font$char);    // Actually write char to the image
            
imageline $img0rand(-$height,$height), $widthrand(-$height,$height), $white);
                        
// Draw some random lines, one for each char, in order to confuse machines a bit more
            
$x    =    $x+($size*1.8);            // Update the x position for the next character
        
}
        
        
// Output the image in PNG format
        
imagepng($img);
        
        
// End of function
    
}
    
    
// Make our captcha
    
makeCaptcha $_SESSION['capTxt'],"banner2.jpg"46090,"./verdana.ttf",32);
?>

check.php

<?php
    session_start
();    // Open session to retrieve captcha data
    
    
$capTxt        =        strtolower $_SESSION['capTxt'] );
    
$capTest    =        strtolower $_POST['cap'] );
    
    if ( empty ( 
$capTest ) ) {
        
// Do nothing and exit
        
die();
    }elseif ( 
$capTxt == $capTest ) {
        echo 
"Code was correct.";
    }else{
        echo 
"Error";
    }

Going Deeper

To begin with, I am going to outline the basic function that the CAPTCHA program itself seeks to succeed, in order to give you at least some understanding as to the methods involved to create anything similar. The first thing that happens is the session handler is opened - this is a server-side type of cookie, meaning that the user cannot access the data held within it - ideal for our captcha text.

The text is then output to a suitably confusing image, and displayed to the visitor. When the user enters the value and submits the form, the PHP script compares the submitted entry with the one stored in the session. If it's a match, odds are the user is a human and can enter codes correctly, so you should probably allow them access to whatever it is you are protecting. Now, let's take a look at the actual code in more detail.

Code Analysis

Let's start at the obvious beginning, the contents of index.php

<?php
    session_start
();        // Initialize the session to save our captcha text
    
$_SESSION['capTxt']    =    md5 microtime() ); // Create a 'random' string
    
$_SESSION['capTxt']    =    substr $_SESSION['capTxt'], 0);    // Shorten it
    
    // This is all that really needs to be done to initialize the captcha, get some HTML on the go
?>

First of all, we initialize the session using the session_start(); command, which essentially opens an array which can be used to store user information on the server, inaccesible to the end-user himself. The use of sessions, rather than cookies, means that it is not possible for the user to simply pull the required captcha text from a cookie.

We then combine the md5(); and microtime(); commands to make a semi-random string of letters and digits - random enough for our purposes, at least - and then abuse the substr(); command to shorten the length of the string down to the desired length. Note the use of the $_SESSION array to access data stored in the PHP session.

Whilst this section of code may seem small and insignificant, it is in-fact an integral component of the captcha, as it generates the text as well as taking care of storing the variables. You must remember to also include session_start(); at the top of any other pages that need to use sessions - making sure to use the command before any output is produced from the script.

The rest of the code in this file is, I'm sure, quite simple to understand - simply being nothing more than a simple HTML form, with an iframe that is used to display the actual output. Note that the iframe is not a requirement, and was simply used in this tutorial to help a user see how the script works when combined together.

Written: 2009-10-13 14:21:16

Website programming, design and content copyright © 2010 Ellis Grouse, all rights reserved.
About - Contact - Links Back to Top

newb

Ellis
Age: 18
Location: Sunderland, England
Occupation: Layabout Student

Befriend: