Captcha (PHP)

Current Version: N/A
Price: FREE

Spammers are the scourge of the internet. They generate crippling amounts of network traffic and create a headache for email users everywhere. One of the easiest ways a spammer can get their messages out is through insecure/open forms. Whether you’re writing a contact form like my PANDA Mailer or you’re creating a user registration system like I’ve developed for PANDA Image Gallery, you need to consider spam control methods. The following code will create a one-off simple captcha security image that is incredibly easy to use and incorporate into nearly any project.

Create a new file named “captcha.php” and paste the following code into the new file. This code will produce an image using the specified dimensions (125px by 30px in the example code–which can be changed to any size). It will also start a named session in order to set a session variable containing the alpha-numeric sequence (string) being displayed in the resulting image. The session variable is how we know what sequence appears in the image without revealing it to bots. It will be used for comparing user input.

//start a named session.

//we'll set a session variable later so we can track store the code being offered to the end user.
@session_name("panda_captcha");
@session_start();

$captchaCodeLength=6;

//dimensions 
$width = 125;
$height = 30;
        
// colors
$bgR = mt_rand(128, 255);
$bgG = mt_rand(128, 255);
$bgB = mt_rand(128, 255);
        
$txtR=$bgR - 128;
$txtG=$bgG - 128;
$txtB=$bgB - 128;

$gridXincrement=24;
$gridYincrement=19;
$angleX=5;
$angleY=5;

/* Random Character String Code 
   ommiting common problematic characters
*/
$characterPool = 'ABCDEFGHJKMNPQRSTUV12345689';
$captchaString = '';
for($x = 0; $x < $captchaCodeLength; $x++){
   $randomPosition = mt_rand(0, strlen($characterPool)-1);
   $captchaString .= substr($characterPool, $randomPosition, 1)." ";
}

//store captcha session variable
$_SESSION['captcha']=str_replace(" ", "", $captchaString);

// create new image with specified dimensions
$image = imagecreate($width, $height);

// generate color
$bgColor = imagecolorallocate($image, $bgR, $bgG, $bgB);
$txtColor = imagecolorallocate($image, $txtR, $txtG, $txtB);

// apply the background
imagefill($image, 0, 0, $bgColor);
 
// Generate a grid to help distort image
for($gridX = 0; $gridX <= $width; $gridX+=$gridXincrement){
    $gridXRAND=mt_rand($gridX, $gridX+3);
    imageline($image, $gridXRAND, 0, $gridXRAND + mt_rand(0, $angleX), $height, $txtColor);
}
for($gridY = 0; $gridY <= $height; $gridY+=$gridYincrement){
    $gridYRAND = mt_rand($gridY, $gridY + 6);
    imageline($image, 0, $gridYRAND, $width, $gridYRAND + mt_rand(0, $angleY), $txtColor);
}

// write the random string to the image
$x=mt_rand(8, 15);
$y=mt_rand(4, 10);
imagestring  ( $image  , 5 , $x , $y, $captchaString, $txtColor );

// put a border on the box
imagerectangle($image, 0, 0, $width - 1, $height - 1, $txtColor);

// set headers to prevent image cache, and identify as gif, output image, clean obj
header('Expires: Tue, 08 Oct 1991 00:00:00 GMT');
header('Cache-Control: no-cache, must-revalidate');
header("Content-Type: image/gif");
imagegif($image);
imagedestroy($image); 

To display the captcha image using the code above you use an html image tag with the above file as the source image. Even though the extension of the “image” is php, the headers outputted by the code above specifies that the image as a gif, thus browsers will be able to properly interpret the image.

<img src="captcha.php" />

Validating the captcha requires retrieving the session variable set by captcha.php when it was included by the html image tag above. The following code will resume the named session and retrieve the verification sequence (string) for comparison. This code should be compared to the data (string) the user submits in the form being validated.

@session_name("panda_captcha");
@session_start();

$challenge=strtolower($_SESSION['captcha']);
$response=strtolower(trim($_POST['response']));

if($challenge == $response){
  //do something
}

To download a fully functional example utilizing the code above click here.


Leave a Reply