How to create captcha in PHP using GD library
Today I will tell you about very important thing – captcha protection. Usually this is very important to prevent automated sign-ups in your registration forms, comment spam in blogs and guestbooks, or another brute force attacks. I will give sample how to draw protection image using our hands.
Here are samples and downloadable package:
Live Demo
[sociallocker]
download in package
[/sociallocker]
Ok, download the example files and lets start coding !
Step 1. HTML
As usual, we start with the HTML.
This is our main page code.
index.html
<script src="js/jquery.min.js"></script> <script src="js/md5.js"></script> <script src="js/main.js"></script> <link rel="stylesheet" href="templates/css/main.css" type="text/css" /> <div class="captcha_example"> <h3><a href="#">Captcha generation using GD, using MD5 to encrypt security text</a></h3> <div> <div style="margin-bottom:10px;"> <h4>Security image:</h4> <img src="captcha.php" class="form_captcha" /> <div class="lines">Verification (Type what you see):</div> <input type="text" name="captcha" value="" class="captcha" /> <button onclick="checkCaptcha()">Check it</button> </div> <p> Current sample draw security image using GD library, each time when page loads it show different symbol-digit combinations. This combination processing through MD5 encription and storing in cookies. So you will able to check cookies after (where it necessary). In my sample I checking it using javascript. Try it! </p> </div> </div>
To display captcha (security image) we will just draw image with php-source: captcha.php. It will generate image for us. Generated text will processed via MD5 and stored in cookies to following recognition and checking.
Step 2. CSS
Here are used CSS styles.
templates/css/main.css
body{background:#eee;font-family:Verdana, Helvetica, Arial, sans-serif;margin:0;padding:0} .captcha_example{background:#FFF;width:865px;font-size:80%;border:1px #000 solid;margin:0.5em 10% 0.5em;padding:1em 2em 2em;-moz-border-radius: 3px;-webkit-border-radius: 3px} .lines{margin:10px 0}
Step 3. JS
Here are necessary JS files to our project.
js/main.js
function getCookie(c_name) { if (document.cookie.length>0) { c_start=document.cookie.indexOf(c_name + "="); if (c_start!=-1) { c_start=c_start + c_name.length+1; c_end=document.cookie.indexOf(";",c_start); if (c_end==-1) c_end=document.cookie.length; return unescape(document.cookie.substring(c_start,c_end)); } } return ""; } function checkCaptcha() { // check captcha var sInsCaptcha = calcMD5($('.captcha').val()); var sCookieCaptcha = getCookie('strSec'); if (sInsCaptcha == sCookieCaptcha) { alert('Wow, great, you enter correct captcha'); } else { alert('Sorry, but wrong'); } }
We will using getCookie function to get cookies information, and checkCaptcha to validate captcha.
js/jquery.min.js and js/md5.js
This is common files – jQuery library with addon for working with MD5. No need to give full code of that file here. It always available as a download package
Step 4. PHP
Ok, here are all used PHP file:
index.php
<?php ob_start(); $chars = array("a","A","b","B","c","C","d","D","e","E","f","F","g","G","h","H","i","I","j","J", "k","K","L","m","M","n","N","o","p","P","q","Q","r","R","s","S","t","T", "u","U","v","V","w","W","x","X","y","Y","z","Z","2","3","4","5","6","7","8","9"); $textstr = ''; for ($i = 0, $length = 5; $i < $length; $i++) $textstr .= $chars[rand(0, count($chars) - 1)]; $hashtext = md5($textstr); setcookie('strSec', $hashtext, 0, '/'); if (produceCaptchaImage($textstr) != IMAGE_ERROR_SUCCESS) { // output header header( "Content-Type: image/gif" ); header("Expires: Mon, 21 Jul 2010 05:00:00 GMT"); header("Last-Modified: " . gmdate("D, d M Y H:i:s") . " GMT"); header("Cache-Control: no-store, no-cache, must-revalidate"); header("Cache-Control: post-check=0, pre-check=0", false); header("Pragma: no-cache" ); // output error image @readfile('captcha/captcha_error.gif'); } ob_end_flush(); function produceCaptchaImage($text) { // constant values $backgroundSizeX = 2000; $backgroundSizeY = 350; $sizeX = 200; $sizeY = 50; $fontFile = "captcha/verdana.ttf"; $textLength = strlen($text); // generate random security values $backgroundOffsetX = rand(0, $backgroundSizeX - $sizeX - 1); $backgroundOffsetY = rand(0, $backgroundSizeY - $sizeY - 1); $angle = rand(-5, 5); $fontColorR = rand(0, 127); $fontColorG = rand(0, 127); $fontColorB = rand(0, 127); $fontSize = rand(14, 24); $textX = rand(0, (int)($sizeX - 0.9 * $textLength * $fontSize)); // these coefficients are empiric $textY = rand((int)(1.25 * $fontSize), (int)($sizeY - 0.2 * $fontSize)); // don't try to learn how they were taken out $gdInfoArray = gd_info(); if (! $gdInfoArray['PNG Support']) return IMAGE_ERROR_GD_TYPE_NOT_SUPPORTED; // create image with background $src_im = imagecreatefrompng( "captcha/background.png"); if (function_exists('imagecreatetruecolor')) { // this is more qualitative function, but it doesn't exist in old GD $dst_im = imagecreatetruecolor($sizeX, $sizeY); $resizeResult = imagecopyresampled($dst_im, $src_im, 0, 0, $backgroundOffsetX, $backgroundOffsetY, $sizeX, $sizeY, $sizeX, $sizeY); } else { // this is for old GD versions $dst_im = imagecreate( $sizeX, $sizeY ); $resizeResult = imagecopyresized($dst_im, $src_im, 0, 0, $backgroundOffsetX, $backgroundOffsetY, $sizeX, $sizeY, $sizeX, $sizeY); } if (! $resizeResult) return IMAGE_ERROR_GD_RESIZE_ERROR; // write text on image if (! function_exists('imagettftext')) return IMAGE_ERROR_GD_TTF_NOT_SUPPORTED; $color = imagecolorallocate($dst_im, $fontColorR, $fontColorG, $fontColorB); imagettftext($dst_im, $fontSize, -$angle, $textX, $textY, $color, $fontFile, $text); // output header header("Content-Type: image/png"); // output image imagepng($dst_im); // free memory imagedestroy($src_im); imagedestroy($dst_im); return IMAGE_ERROR_SUCCESS; } ?>
Here are several comments by code:
In start we will define array of used characters – $chars. After, we will compose string (5 letters) with random characters. After, will MD5 this result string and save it into cookies. We will use this to more security. So any bot or special script will unable to find this key even after detail investigation of result page.
produceCaptchaImage is main function which will draw our captcha. It take just 1 param – text which we going to draw. We will using GD library to draw. We will randomly choose position to text in captcha, angle (+- 5 degrees), font color. After will get our background image which will mage reading of our code more difficult, and, will draw result text on this image.
Live Demo
Conclusion
Today I told you how to create our own captcha – security image. I sure that you will use it in your projects. Quite any serious project using it to protect spamming. Good luck!
This is main think for every one use captcha in your free web script and buy script…
Speechless! Excellent post
Thank you, you have been most helpful.
check Captcha at client side is not a good idea?
The attacker can easily bypass it.
Yes, I know, firebug give us big possibilities. But I gave main conception. You can just submit some form with captcha, and check this validation directly at server using PHP. All possible ;-)
Thanks for u r information
its very useful
Just saying thanks will not just be sufficient, for the tremendous lucidity in your posts. I will right away grab your feed to stay abreast of any updates. Many posts are very dry and hard to read, but yours has been very well written and informational!
Bookmarked good sir! Also, love the code snippets. Is it a plugin that lets you do that? I’ve seen it around.
Give a proper way how can i use capcha in my form
2 Raju Khatak
Check our JS file, where I alerting about success, in this place you can allow to submit your form !
I am creating a test form first before putting it on my site. So far everything works OK but I wish the user to be redirected when clicking OK in the ‘yes’ alert. I have put a location in the javascript but it just goes back to the a refreshed form and not to the required location. Below is the relevant section of main.js, what am I doing wrong?
——————
function checkCaptcha() {
// check captcha
var sInsCaptcha = calcMD5($(‘.captcha’).val());
var sCookieCaptcha = getCookie(‘strSec’);
if (sInsCaptcha == sCookieCaptcha) {
window.alert(‘Click OK to submit’)
window.location.href = ‘custom_website_url’;
} else {
alert(‘Sorry, but wrong’);
}
}
Hello Andrew,
Your changes are correct, I’ve just tested it and it relocates to another url once you enter a correct captcha
Excellent work, thank you! I just replaced my sometimes-working CAPTCHA code with your produceCaptchaImage() routine and all was ready and working. :-) (with server side check, of course, but I had that part already, just had troubles with image creating). Thanks!
Hm, by the way, some of those error constants were undefined for me, but I simply changed it to return true/false.