Creating a basic captcha with Imagick
I hate captcha systems, truly, madly, deeply. But spammers force us to create and use them.
Writing captcha systems can be very easy. You need a randomly generated image, a hard to read font, and finally basic server side coding knowledge. I use PHP cos it’s well documented and extremely easy to use, but you can use any other server side language you want. On which ImageMagick can be used of course.
So, let’s list what we want to do:
- Create a random string
- Display it as an image
- Check whether the user entered the string correctly
That’s all.
Creating random string with PHP
This is the easiest. PHP already has a function which creates new random string each second. Yup, that’s the time() function. But the created string has only numbers. To fix that, we encrypt it with some sort of built-in encryption function. That can be md5, sha1, anything. I use md5 now cos that’s which popped in my mind on the first place.
The second thing we want to solve is to not make the user to enter 32 characters, but only 5. Again, PHP’s string manipulation knowledge comes handy, I use substr(). So let’s see our code:
$rand = md5(time()); $str = substr($rand, 0 , 5);
That simple. We now have a 5 characters long completely random string.
Pushing the random string in an image, using IMagick
If you followed my IMagick related posts, you should know that annotating an image with IMagick is simpler than confusing a snail with a mirror. The only difference is that now we’ll have in the image our random string, not a fixed variable’s value. Yeah, that’s dynamic image.
I’ll also use a hard to read font, because using DirectX even a 5-year-old can create a captcha reading software if we use a common font.
You may ask how will the server side code which checks whether the captcha is correct or not will know the user entered the correct code or not. That’s solved with sessions. We start our session in the image generator script, and set the shortened version of our random string in a session variable.
So, when the image is loaded in your HTML, the session variable will get the 5 character long random string as value. The session variable will be checked on the page which checks the user input, if matches the value which was entered by the user, we know it’s human. No, we hope it’s a human.
So, the code to generate the dynamic captcha image:
session_start();
$rand = md5(time());
$str = substr($rand, 0 , 5);
$_SESSION['captcha'] = $str;
$font = '/path/to/your/hard2read/font.ttf';
$image = new Imagick();
$draw = new ImagickDraw();
$pixel = new ImagickPixel( 'white' );
$image->newImage(100, 27, $pixel);
$draw->setFont($font);
$draw->setFontSize( 25 );
$draw->line( $x, $y, $x1, $y1 );
$image->annotateImage($draw, 10, 20, 0, $str);
$image->setImageFormat('png');
header('Content-type: image/png');
echo $image;
We save the above code as captcha.php and try to load it. If everything went well, we should see an image like the one on the left.
The HTML form for our captcha
If you can’t do this by your own, you shouldn’t mess with captcha verification. But just for the sake of the example:
Now the server side script which checks the user input. I write something very basic, don’t validate or sanitize anything. When you write your own user input verifier code, you should validate every single bit of your users’ input, don’t trust em!
session_start();
/*Check if every field has been filled in*/
if (!empty($_POST['uname']) && !empty($_POST['upass']) && !empty($_POST['captcha'])){
/*Check if the CAPTCHA image value matches the user input*/
if ($_SESSION['captcha'] != $_POST['captcha']){
echo 'You failed the CAPTCHA verification. Try again.';
}else{
echo 'Congrats! Everything is cool!';
}
}else{
echo 'You missed to fill in some fields. Try again.';
}
And we’re done.
To play with the example you can do it here.
To download the files which were created through this post, click here.

Recent Comments