Have you ever seen popular sites that block
automated registrations with an image that has some garbled string?
These are extremely hard for a computer to read, but they are extremely
easy to generate.
Have you ever seen popular sites that block automated registrations
with an image that has some garbled string? These are extremely hard
for a computer to read, but they are extremely easy to generate.
The
only things you need are GD (to create the images), a nice font (it's
got to look good, no?), and a couple minutes of time to read and follow
along with this tutorial.
This is going to require a session.
Don't worry if you've never used them before, you'll hardly even notice
their presence. In the beginning of the file, we just need to session_start();
to tell it to start the session. This session is only going to hold one
variable: what the image says. We obviously need to keep track of this
so we can check whether or not the user has entered the correct string
(and, thus, is a human).
We now need a form, something to get the
input from the user. It also needs to display the image, of course. If
you want to do this all in one page, keep in mind that you will need to
output either the form or the image, never both at the same time. You can do this by setting a GET variable when you want to display the image: file.php?showimage=true.
Somewhere in the form file, you need to set a session variable for the
word on the image. Make sure this isn't output to the user, or the
entire script is ruined. One can set a session variable by using $_SESSION["variable"] = "value";. Of course, you're going to want to use a more random string, but a static one will do for now. Here's what I am using: $_SESSION["crc"] = chr(rand(0,25)+97). chr(rand(0,25)+97). chr(rand(0,25)+97). rand(0,9). rand(0,9). rand(0,9);
Now
we can start to generate the image. I like to use TrueType Fonts (TTF),
but you can feel free to use whatever type you want--GD has several
different accepted font types. To get the size of the image we're going
to create, we need to use a bounding box, imagettfbbox() is what I'll be using.
Now
that we have dimensions for the image, let's garble it up a bit. A
bunch of random polygons will do the trick. I will be using this
complex algorithm:
for ($x=0; $x<15; $x++) {
for ($y=0; $y<7; $y++) {
$color = imagecolorclosest($im, rand(100,255), rand(100,255), rand(100,255));
$points = array(
rand(-5,5)+rand(5*$x,10*$x), rand(-5,5)+rand(5*$y,10*$y),
rand(-5,5)+rand(5*$x,10*$x), rand(-5,5)+rand(5*$y,10*$y),
rand(-5,5)+rand(5*$x,10*$x), rand(-5,5)+rand(5*$y,10*$y),
rand(-5,5)+rand(5*$x,10*$x), rand(-5,5)+rand(5*$y,10*$y)
);
imagefilledpolygon($im,$points,3,$color);
}
}
After
the polygon background has been drawn, go ahead and put the text on the
image. Remember to use the same settings you used in the bounding box,
or it won't fit in the image right. Tweek your settings on the bounding
box and the text so you can get it to look how you want.
You're
almost done. All you need to do is check if the value that was sent in
by the user (from the previously created form) matches the session
value. This is a very simple if: if ($_POST["word"] == $_SESSION["crc"]) { }
You're done! Here's a copy of my file in case you have any trouble with the tutorial:
session_start();
if (isset($_POST["word"])) {
if (strtolower($_SESSION["crc"]) == strtolower($_POST["word"])) {
echo("Matched!");
}
else {
echo("Didn't match.");
}
}
else {
$self = $_SERVER['PHP_SELF'];
if ($_GET["im"] == TRUE) {
$mycrc = $_SESSION["crc"];
header("Content-type: image/png");
$size = imagettfbbox(30, 3, "../Fonts/georgia.ttf", $mycrc);
$im = imagecreatetruecolor(abs($size[4]-$size[0]), (abs($size[5])+$size[1]));
$white = imagecolorallocate($im, 255, 255, 255);
imagefill($im, 0, 0, $white);
$black = imagecolorallocate($im, 0, 0, 0);
for ($x=0;$x<15;$x++) {
for ($y=0;$y<7;$y++) {
$color = imagecolorclosest($im, rand(100,255), rand(100,255), rand(100,255));
$points = array(
rand(-5,5)+rand(5*$x,10*$x), rand(-5,5)+rand(5*$y,10*$y),
rand(-5,5)+rand(5*$x,10*$x), rand(-5,5)+rand(5*$y,10*$y),
rand(-5,5)+rand(5*$x,10*$x), rand(-5,5)+rand(5*$y,10*$y),
rand(-5,5)+rand(5*$x,10*$x), rand(-5,5)+rand(5*$y,10*$y)
);
imagefilledpolygon($im, $points, 3, $color);
}
}
imagettftext($im, 27, 4, 5, 33, $black, "../Fonts/georgia.ttf", $mycrc);
imagepng($im);
exit();
}
$_SESSION["crc"] = chr(rand(0,25)+97) . chr(rand(0,25)+97) . chr(rand(0,25)+97) . rand(0,9) . rand(0,9) . rand(0,9);
echo <<<END
<img src="$self?im=1" alt="Please type this word."><br />
<form method="post" action="$self">
Please type the above word:<br />
<input type="text" name="word" value=""><br />
<input type="submit" name="submit" value="Submit Query">
</form>
END;
}
|