Synook

A basic PHP captcha

Due to excessive spam, I recently implemented a captcha system for the comments on this blog. The image generated didn’t have to be super-complex, so I came up with a very easy process using PHP’s GD image library.

First, we start the session, because we want to be able to pass the generated value onto our form’s processing page, and we do that through a session.

session_start();

Then, we set the content-type header to an image format, for our purposes PNG.

header("content-type:image/png");

Now, we create the image we want, and the colors we are going to use, before coloring the entire image in our background color.

$capacha = imagecreatetruecolor(80, 22);
$back = imagecolorallocate($capacha, 0x19, 0x19, 0x19);
$front = imagecolorallocate($capacha, 0xBB, 0xBB, 0xBB);
imagefill($capacha, 0, 0, $back);

Now, we generate a random number bewteen 10000 and 99999 (because we want the captcha to have five numbers), and then store it to the session variable that will be read on the next page. To prevent conflicts we will allow a tag querystring variable to be concatenated on the session index to differentiate between different captcha’s codes.

$rand = rand(10000, 99999);
$tag = isset($_GET['tag']) ? "_{$_GET['tag']}" : ""; 
$_SESSION["blog_capacha$tag"] = $rand;

Now we can draw the random number onto the image. To make it a bit harder for bots to read (it also looks nicer) we will randomise the y-position of each number.

for ($i = 0; $i <= 4; $i++)
    imagechar($capacha, 3, 12*($i+1), rand(0,9), substr($rand,$i,1), $front);

Now for the bit that makes it hard for machines to read. It is actually quite simple, but the resulting anti-aliasing blur I believe will confuse machines. Basically, we turn on anti-aliasing (alpha-blending) and rotate the image 20 degrees clockwise.

imagealphablending($capacha, true);
$capacha = imagerotate($capacha, 10, $back);

Now, we just output the image, and we are done!

imagepng($capacha);