Jas
07-04-2008, 04:12 AM
Create image validation
In this tutorial:
Create your own (simple) version of CAPTCHA
Learn about PHP image functions
What you need:
A basic knowledge of PHP
A PHP Enabled server
30 minutes
What is image validation?
You've most likely seen by those annoying forms with CAPTCHA-- "Please type the characters in the image" they say. The concept behind them is simple: computers cannot read like humans can, so by forcing a user to read something and copy it, it should prevent computers from posting information to a server. While some of them are extremely hard to read, they generally work well for weeding out the pesky web bots. Actually, they also effectively block form submissions that are not coming from your website. No, they aren't perfect, but they generally work well.
So, what are we waiting for? Lets make a simple one using PHP to help protect our forms.
Our string
First, we need to generate the characters to place in our image. Take a look at this:
<?php
SESSION_START();
$_SESSION['captcha'] = '';
$captcha_chars = array('2','3','4','5','6','7','8','9','A','B','C','D','E','F','G','H','J','K','M','N','P','Q','R','S','Y','U','V','W','X','Y','Z');
for($i = 0; $i < 5; $i++){
$rand_char = rand(0, (count($captcha_chars) -1));
$_SESSION['captcha'] .= $captcha_chars[$rand_char];
}
?>
(Notice that similar characters like 0 and O, and I and 1 have been removed from the array so the user does not get confused.)
That block of code should be self explanatory, but just in case, I'll briefly explain. We are starting a session to store the string in so that our image and the form validation process can have access to the string. Then, we generate five random characters via the rand() function.
With that out of the way, we are going to need to use PHP's relatively decent image functions (http://us3.php.net/manual/en/ref.image.php).
The image
Let's create an image. To do this, we start by calling the function createimage().
$im = imagecreate(200, 60);
Here we have declared our image to be 200px in width, and 60px in height.
Lets create some colors for our image:
$bg_color = imagecolorallocate($im, 0, 122, 87); //This is the bg color
$font_color = imagecolorallocate($im, 0, 0, 0);
Okay, lets stop and see what we've done so far. By adding three more lines of code to the end, we can see our image:
<?php
SESSION_START();
$_SESSION['captcha'] = '';
$captcha_chars = array('2','3','4','5','6','7','8','9','A','B','C','D','E','F','G','H','J','K','M','N','P','Q','R','S','Y','U','V','W','X','Y','Z');
for($i = 0; $i < 5; $i++){
$rand_char = rand(0, (count($captcha_chars) -1));
$_SESSION['captcha'] .= $captcha_chars[$rand_char];
}
$im = imagecreate(200, 60);
$bg_color = imagecolorallocate($im, 0, 122, 87);
$font_color = imagecolorallocate($im, 0, 0, 0);
header("Content-type: image/png"); // We are telling the browser that there is an image coming
imagepng($im); // Now we are outputting the image
imagedestroy($im); // Now we are deleting the image resource
?>
Wasn't that fun? :p Hopefully the code is working and you see a small image. If not, now is the time to rewind the tape and correct your mistakes so far.
Drum roll please. We are about to add the text! First, we need to change the string into an array of single characters. I prefer preg_split(), but you can use whatever you like:
$characters = preg_split("//", $_SESSION['captcha'], -1, PREG_SPLIT_NO_EMPTY);
(Notice the PREG_SPLIT_NO_EMPTY flag on the end-- we don't want any blank characters).
And here is where it gets tricky. Find the Arial font and place it in the folder with the script, because we need it for inserting the text. Once you've done that, your ready for this:
$x = 5; // Start the characters 5px from left
foreach($characters as $char){
$y = rand(25,45); // Y cord or char
$size = rand(16,28); // Font size for char
$rotation = rand(-17,17); // Rotation of char
// INSERT CHAR HERE IN A MINUTE
$x += 38; // X cord of char
}
So far all this does is set of some random params for the character to be inserted. To insert the text, we use a somewhat confusing function called imagettftext(). Here is how we will use it:
imagettftext($im, $size, $rotation, $x, $y, $font_color, './arial.ttf', $char);
The big finish
Thus, our finished code is something like this:
<?php
SESSION_START();
$_SESSION['captcha'] = '';
$captcha_chars = array('2','3','4','5','6','7','8','9','A','B','C','D','E','F','G','H','J','K','M','N','P','Q','R','S','Y','U','V','W','X','Y','Z');
for($i = 0; $i < 5; $i++){
$rand_char = rand(0, (count($captcha_chars) -1));
$_SESSION['captcha'] .= $captcha_chars[$rand_char];
}
$im = imagecreate(200, 60);
$bg_color = imagecolorallocate($im, 0, 122, 87);
$font_color = imagecolorallocate($im, 0, 0, 0);
$characters = preg_split("//", $_SESSION['captcha'], -1, PREG_SPLIT_NO_EMPTY);
$x = 5;
foreach($characters as $char){
$y = rand(25,45);
$size = rand(16,28);
$rotation = rand(-17,17);
imagettftext($im, $size, $rotation, $x, $y, $font_color, './arial.ttf', $char);
$x += 38;
}
header("Content-type: image/png");
imagepng($im);
imagedestroy($im);
?>
If you want to get fancy, you can add random lines or a background image, but that's beyond this tutorial.
To insert the image into your form, place this next to the text input in which you wish the have the user type the captcha string:
<img src="./path_to_script/script_name.php" />
To check against the users input, do something like this in the form process:
if($_POST['captcha'] != $_SESSION['captcha']){die('Incorrect captcha entry');}
Thanks for reading this, and I hope you learned something.
EDIT:
----------------------
djr33 was kind enough to put a modified version of the script online. The online version features some distortion.
http://ci-pro.com/misc/jascaptcha -- View retult
http://ci-pro.com/misc/jascaptcha/code.txt -- View code
In this tutorial:
Create your own (simple) version of CAPTCHA
Learn about PHP image functions
What you need:
A basic knowledge of PHP
A PHP Enabled server
30 minutes
What is image validation?
You've most likely seen by those annoying forms with CAPTCHA-- "Please type the characters in the image" they say. The concept behind them is simple: computers cannot read like humans can, so by forcing a user to read something and copy it, it should prevent computers from posting information to a server. While some of them are extremely hard to read, they generally work well for weeding out the pesky web bots. Actually, they also effectively block form submissions that are not coming from your website. No, they aren't perfect, but they generally work well.
So, what are we waiting for? Lets make a simple one using PHP to help protect our forms.
Our string
First, we need to generate the characters to place in our image. Take a look at this:
<?php
SESSION_START();
$_SESSION['captcha'] = '';
$captcha_chars = array('2','3','4','5','6','7','8','9','A','B','C','D','E','F','G','H','J','K','M','N','P','Q','R','S','Y','U','V','W','X','Y','Z');
for($i = 0; $i < 5; $i++){
$rand_char = rand(0, (count($captcha_chars) -1));
$_SESSION['captcha'] .= $captcha_chars[$rand_char];
}
?>
(Notice that similar characters like 0 and O, and I and 1 have been removed from the array so the user does not get confused.)
That block of code should be self explanatory, but just in case, I'll briefly explain. We are starting a session to store the string in so that our image and the form validation process can have access to the string. Then, we generate five random characters via the rand() function.
With that out of the way, we are going to need to use PHP's relatively decent image functions (http://us3.php.net/manual/en/ref.image.php).
The image
Let's create an image. To do this, we start by calling the function createimage().
$im = imagecreate(200, 60);
Here we have declared our image to be 200px in width, and 60px in height.
Lets create some colors for our image:
$bg_color = imagecolorallocate($im, 0, 122, 87); //This is the bg color
$font_color = imagecolorallocate($im, 0, 0, 0);
Okay, lets stop and see what we've done so far. By adding three more lines of code to the end, we can see our image:
<?php
SESSION_START();
$_SESSION['captcha'] = '';
$captcha_chars = array('2','3','4','5','6','7','8','9','A','B','C','D','E','F','G','H','J','K','M','N','P','Q','R','S','Y','U','V','W','X','Y','Z');
for($i = 0; $i < 5; $i++){
$rand_char = rand(0, (count($captcha_chars) -1));
$_SESSION['captcha'] .= $captcha_chars[$rand_char];
}
$im = imagecreate(200, 60);
$bg_color = imagecolorallocate($im, 0, 122, 87);
$font_color = imagecolorallocate($im, 0, 0, 0);
header("Content-type: image/png"); // We are telling the browser that there is an image coming
imagepng($im); // Now we are outputting the image
imagedestroy($im); // Now we are deleting the image resource
?>
Wasn't that fun? :p Hopefully the code is working and you see a small image. If not, now is the time to rewind the tape and correct your mistakes so far.
Drum roll please. We are about to add the text! First, we need to change the string into an array of single characters. I prefer preg_split(), but you can use whatever you like:
$characters = preg_split("//", $_SESSION['captcha'], -1, PREG_SPLIT_NO_EMPTY);
(Notice the PREG_SPLIT_NO_EMPTY flag on the end-- we don't want any blank characters).
And here is where it gets tricky. Find the Arial font and place it in the folder with the script, because we need it for inserting the text. Once you've done that, your ready for this:
$x = 5; // Start the characters 5px from left
foreach($characters as $char){
$y = rand(25,45); // Y cord or char
$size = rand(16,28); // Font size for char
$rotation = rand(-17,17); // Rotation of char
// INSERT CHAR HERE IN A MINUTE
$x += 38; // X cord of char
}
So far all this does is set of some random params for the character to be inserted. To insert the text, we use a somewhat confusing function called imagettftext(). Here is how we will use it:
imagettftext($im, $size, $rotation, $x, $y, $font_color, './arial.ttf', $char);
The big finish
Thus, our finished code is something like this:
<?php
SESSION_START();
$_SESSION['captcha'] = '';
$captcha_chars = array('2','3','4','5','6','7','8','9','A','B','C','D','E','F','G','H','J','K','M','N','P','Q','R','S','Y','U','V','W','X','Y','Z');
for($i = 0; $i < 5; $i++){
$rand_char = rand(0, (count($captcha_chars) -1));
$_SESSION['captcha'] .= $captcha_chars[$rand_char];
}
$im = imagecreate(200, 60);
$bg_color = imagecolorallocate($im, 0, 122, 87);
$font_color = imagecolorallocate($im, 0, 0, 0);
$characters = preg_split("//", $_SESSION['captcha'], -1, PREG_SPLIT_NO_EMPTY);
$x = 5;
foreach($characters as $char){
$y = rand(25,45);
$size = rand(16,28);
$rotation = rand(-17,17);
imagettftext($im, $size, $rotation, $x, $y, $font_color, './arial.ttf', $char);
$x += 38;
}
header("Content-type: image/png");
imagepng($im);
imagedestroy($im);
?>
If you want to get fancy, you can add random lines or a background image, but that's beyond this tutorial.
To insert the image into your form, place this next to the text input in which you wish the have the user type the captcha string:
<img src="./path_to_script/script_name.php" />
To check against the users input, do something like this in the form process:
if($_POST['captcha'] != $_SESSION['captcha']){die('Incorrect captcha entry');}
Thanks for reading this, and I hope you learned something.
EDIT:
----------------------
djr33 was kind enough to put a modified version of the script online. The online version features some distortion.
http://ci-pro.com/misc/jascaptcha -- View retult
http://ci-pro.com/misc/jascaptcha/code.txt -- View code