Aug 11 2009

Create A Simple Captcha With PHP and GD

Everyone hates captchas. I know I do. It sucks but they are a necessary evil. Most captchas are difficult (sometimes impossible) to read and they will consistantly drive visitors from your site. I’ve been on sites where the captcha was so hard to decipher that I’ve never gone back.

During the development of a new site I was forced to create one of these evil entities. It was surprisingly simple and painless. The captcha that I outline here is very, very simple and should never be used in production without a fair amount of tweaking.

Having developed my site using php I naturally turned to the GD library.

Firstly I generated a random string to display on the captcha :


//generate a random alphanumeric string of a specific length
function gen_random_string($length) 
{
  $characters = "0123456789ABCDEFGHIJKLMNOPQRSTUVWZYZ".
        "abcdefghijklmnopqrstuvwxyz";
  $real_string_length = strlen($characters) - 1;
  for($p=0;$p<$length;$p++)
  { $string .= $characters[mt_rand(0, $real_string_length)]; }
  return $string;
}

//add to session array so other scripts can access it for the comparison
$_SESSION['image_text']= gen_random_string(8);

//split into character array - str_split only works in PHP 5
$text_array = str_split($_SESSION['image_text']);


Now that I have my string I need to create the image. Make sure that GD is installed on your php apache server.

//create the image with a background image
$NewImage =imagecreatefrompng("bg1.png");
$cntr = 0;
foreach($text_array as $letter)
{
  //generate a random color for each letter
  $r = rand(0,200);
  $g = rand(0,200);
  $b = rand(0,200);
  $textcolor = imagecolorallocate($NewImage, $r, $g, $b);

  //random horizontal spacing
  $spacing = (rand(5,10)+($cntr*10));
  
  //add the character to the image
  imagestring($NewImage, 5, $spacing, rand(0,10), $letter, $textcolor);
  $cntr++;
}


The code above will generate a GD captcha image with random coloring and random horizontal and vertical spacing on top of a background image.
Now we just need to output it.

//output the headers than the image as a PNG
header('Content-type: image/png');
header('Cache-Control: max-age=0');
header('Expires: '.gmdate('r',time()-3600*24*365));
header('Pragma:');
ImagePNG($NewImage);
imagedestroy($NewImage);


So if I called this file simple-captcha.php I could call it with this html:

<img id='captcha' name='captcha' src="simple-captcha.php">


Here is what it looks like :

This captcha can be strengthened by using other GD image functions such as imagefilledellipse and imageline to create artifacts in the background. It also helps to use different fonts and to change the angle of the letters.

Share