A web developer's blog. PHP, MySQL, CakePHP, Zend Framework, Wordpress, Code Igniter, Django, Python, CSS, Javascript, jQuery, Knockout.js, and other web development topics.

Simple CAPTCHA Tutorial with Zend Framework

UPDATE 2008-10-24 This guy has an updated post for Zend_Captcha. Mine is old an out-dated.

Here is how to create a simple Captcha image with the Zend Framework.

I have created this controller named: ImagegeneratorController. The job of this controller is to display images – whether from a database blob or in this case, an image created on the fly.

< ?php
class ImagegeneratorController extends Zend_Controller_Action
{
public function init()
{
$this->_helper->viewRenderer->setNoRender();
}
 
public function generatecaptchaAction()
{
 
//Let's generate a totally random string using md5
$md5_hash = md5(rand(0,999));
//We don't need a 32 character long string so we trim it down to 5
$security_code = substr($md5_hash, 15, 5);
 
$_SESSION['captcha_code'] = $security_code;
 
//Set the image width and height
$width = 100;
$height = 20;
 
//Create the image resource
$image = ImageCreate($width, $height);
 
//We are making three colors, white, black and gray
$white = ImageColorAllocate($image, 255, 255, 255);
$black = ImageColorAllocate($image, 0, 0, 0);
$grey = ImageColorAllocate($image, 204, 204, 204);
 
//Make the background black
ImageFill($image, 0, 0, $black);
 
//Add randomly generated string in white to the image
ImageString($image, 3, 30, 3, $security_code, $white);
 
//Throw in some lines to make it a little bit harder for any bots to break
ImageRectangle($image,0,0,$width-1,$height-1,$grey);
imageline($image, 0, $height/2, $width, $height/2, $grey);
imageline($image, $width/2, 0, $width/2, $height, $grey);
 
//Tell the browser what kind of file is come in
header("Content-Type: image/jpeg");
 
//Output the newly created image in jpeg format
ImageJpeg($image);
}
}

Now, anywhere in my view file (.phtml), I can do this to display the image:

...
<img src="http://blog.ekini.net/wp-admin/%3C?php%20echo%20$this-%20/%3EbaseUrl.%27/imagegenerator/generatecaptcha%27%20?%3E" />
...

That’s about it. To check if there is are any errors, try to http://yoursite.com/imagegenerator/generatecaptcha – it should display the image. From there you can debug for errors if there are any.

*Update*
Apparently, I forgot to store $security_code variable into a session variable. This value will be used to verify if the user has entered the correct security code after submitting the form.

The test form:
< form action="/path/to/controller/action" method="post">
Captcha Code:
<img src="< ?=$this-/>baseUrl?>/imagegenerator/generatecaptcha" />
Enter Code Here:
<input name="entered_coded" type="text" />
<input value="Submit" type="button" />

Now, in the controller that will handle the form, you will have something like this:

...
public function handlecaptchaAction()
{
$entered_captcha = /*get from POST*/;
if ($entered_captcha != $_SESSION['captcha_code']) {
echo 'You are a bot!!!';
}
//rest of the code here...
}
...

Resources: http://www.webcheatsheet.com/php/create_captcha_protection.php
Thanks to: DanielF and Booster in #zftalk

Post your comments / corrections below. Thanks!

Update:

Hi, just a suggestion, to update your code… For example when a user opens 2 posts with the same image, he won’t be able to post the first opened article (or what ever). I suggest naming the session variable ‘captcha_code’.post_id. And to pass the variable, use /imagegenerator/generatecaptcha/post_id/id.

BY: Tomas on 30 May 2008 at 4:38 pm

This entry was posted in Uncategorized. Bookmark the permalink.

43 Responses to Simple CAPTCHA Tutorial with Zend Framework

  1. Pharalia says:

    Fantastic! Just what I have been looking for.

    One suggestion, would it not be more desirable to build the captcha processor into a model? That way the code could easily be integrated with other form processing.

  2. Wenbert says:

    Thanks Pharalia. Hmmm I haven’t thought of it that way. I guess you could put it in a model, but I’m thinking that models in MVC do databases. That is why I created a new controller for it. But I say, whatever works for you, works for me as well ;)

  3. Emeric says:

    Build a captcha image and show it is easy.
    But how to integration it ZF is difficulty more.
    $form->addElements(‘captcha’) :)

  4. Wenbert says:

    @Emeric: This tutorial came out before Zend_Form was included in the 1.5 release. I do not know how to do a captcha image using Zend_Form yet :P

  5. Luca says:

    Sorry but this doesn’t work for me. I’m using ZF 1.5 but when i call the action its return only a string that is the alt html attributes of the image. Your code looks works out of zf (i try it in a single script).

  6. Wenbert says:

    Luca, please make sure that you have placed no-render on your code:
    $this->_helper->viewRenderer->setNoRender();

    … and garbage comes out of your browser, then it isn’t displaying the proper headers. You can do so by putting this line:
    header(“Content-Type: image/jpeg”);

    I have a working example here:
    http://mylyricsfinder.com/imagegenerator/generatecaptcha

  7. Tomas says:

    Hi, just a suggestion, to update your code… For example when a user opens 2 posts with the same image, he won’t be able to post the first opened article (or what ever). I suggest naming the session variable ‘captcha_code’.post_id. And to pass the variable, use /imagegenerator/generatecaptcha/post_id/id.

  8. Wenbert says:

    Hi Tomas,

    Thank you for your suggestion. I am updating the post above with your suggestion so that it will be easier for the other readers.

    Thanks so much! ^_^

  9. sangbima says:

    Nice tutorial, but your code didn’t work for me. On my browser display: “http://localhost/imagegenerator/generatecaptcha”. No image displaye. I’ve copy your code, to my app, any suggest for my problem? Thx. (Sory for my bad English).

  10. Wenbert says:

    hi sangbima,

    Can you http://paste2.org your code?
    Are you getting error messages? Please provide more details. I would be glad to help you out.

    Thanks,
    Wenbert

  11. sangbima says:

    This my Controller:

    class ImagegeneratorController extends Zend_Controller_Action {
    public function init()
    {
    $this->_helper->viewRenderer->setNoRender();
    }
    /**
    * The default action – show the home page
    */
    public function generatecaptchaAction() {
    //Let’s generate a totally random string using md5
    $md5_hash = md5(rand(0,999));
    //We don’t need a 32 character long string so we trim it down to 5
    $security_code = substr($md5_hash, 15, 5);

    $_SESSION['captcha_code'] = $security_code;

    //Set the image width and height
    $width = 100;
    $height = 20;

    //Create the image resource
    $image = ImageCreate($width, $height);

    //We are making three colors, white, black and gray
    $white = ImageColorAllocate($image, 255, 255, 255);
    $black = ImageColorAllocate($image, 0, 0, 0);
    $grey = ImageColorAllocate($image, 204, 204, 204);

    //Make the background black
    ImageFill($image, 0, 0, $black);

    //Add randomly generated string in white to the image
    ImageString($image, 3, 30, 3, $security_code, $white);

    //Throw in some lines to make it a little bit harder for any bots to break
    ImageRectangle($image,0,0,$width-1,$height-1,$grey);
    imageline($image, 0, $height/2, $width, $height/2, $grey);
    imageline($image, $width/2, 0, $width/2, $height, $grey);

    //Tell the browser what kind of file is come in
    header(“Content-Type: image/jpeg”);

    //Output the newly created image in jpeg format
    ImageJpeg($image);
    }
    }

    Then My View:

    img src=”imagegenerator/generatecaptcha” alt=”captcha”

    No error message on My Display.

  12. Wenbert says:

    Hi sangbima,

    I made an error on my post. Please do this in you view:
    Security Code: < img src="< ?php echo $this->baseUrl.’/imagegenerator/generatecaptcha’ ?>” />

    You have to echo it with the baseUrl.

  13. sangbima says:

    Still not working for me. :(

  14. Wenbert says:

    hmmm strange. can you give me a “view source” of your < img > tag?

  15. sangbima says:

    < img src=”baseUrl.’/imagegenerator/generatecaptcha’?>” />

    I try to write like this:

    , still didn’t work. :(

  16. Wenbert says:

    sangbima, nope that won’t work.
    $this->baseUrl is supposed to display your base URL. The baseUrl should be something like: http://localhost/appname

    Try this:
    In your controller, do this:
    $this->view->baseUrl = $this->_request->getBaseUrl();

    Then in you .phtml file, you should be able to use $this->baseUrl
    The IMG tag in your .phtml / view file should look something like this:
    < img src=”baseUrl ?>’/imagegenerator/generatecaptcha’?>” />

    the output should be like:
    < img src=”http://localhost/appname/imagegenerator/generatecaptcha” />

    The syntax in your .phtml is totally wrong. ^_^

  17. Siro says:

    Hi,
    sangbima try changing $_SESSION[‘captcha_code’] = $security_code; in your controller. Those quote marks should be ‘ or “. I had the same problem and that solved it.

  18. Amit Shah says:

    Good tutorial..
    I have tried the coding and its working :)
    The question is how to make a bigger font size, I have tried but it allow only 5 as maximum font size.
    ImageString($image, 5, 30, 3, $security_code, $white);

  19. Peter Hons says:

    Didn’t work for me either.
    I just get (in safari) a question mark so he doesn’t find an image.

    Saving the captcha picture is working, so I just overwrite the captcha picture and save it, and show this image.

  20. Wenbert says:

    @Peter Hons, maybe you can Paste2.org your code so that we can take a look at it?

  21. Sudarshan says:

    Hello,
    I am using this code in a sample test I am working on.
    In the application the Layout is used .But when the layout is enabled the image is not generated.Without layout image is generated.
    What should I do?

  22. Wenbert says:

    @Sudarshan, I am not sure. I have not tested this with the layouts. But I am thinking that you need to “disable” layouts for the ImagegeneratorController and its actions because the HTML tags in the Layout will be rendered with the images.

    Instead of outputting the image, the Layout interferes with the HTML tags, etc. because the layout is parsed first before the action (the image) is rendered.

  23. Snowcore says:

    Thanks.
    Do you like Zend_Captcha ?

  24. Wenbert says:

    Snowcore, I haven’t used Zend_Captcha yet…

  25. darkhorse says:

    anyone can show how to use the internal Zend_Captcha to generate an image?

  26. manjava says:

    someone can you explain for me how can generate the code the captcha with zend framework 1.6

    thanks

  27. edazevedo says:

    I’m getting this error
    “Call to undefined function ImageCreate()”

    How do I include this function?

    Thanks

  28. Wenbert says:

    @edazevedo make sure that your ImagegeneratorController is working. You do not have to “include” this function. It simply works once you have your Zend Framework setup in you application. See http://framework.zend.com/manual/en/zend.controller.html for more information.

  29. edazevedo says:

    I’ve got my zend framework up and running :)
    Controllers are working ok.
    Isn’t ImageCreate() a function from the PHP GD-extension, or other?
    It just don’t seem to be from the Zend Framework library.

    Thanks

  30. edazevedo says:

    Problem solved. I’ve just installed the PHP GD-extension and it started working.

    I’m using ubuntu, so I get the package with:
    sudo apt-get install php5-gd

    and restarted my apache server:
    sudo /etc/init.d/apache2 restart

    and that’s it.

  31. Diptesh Patel says:

    Hi, All

    Here in this code Header is defined like this
    header(“Content-Type: image/jpeg”);
    So it will might not give you the result
    Try this header instead of :

    $this->_response->setHeader(‘Content-Type’, ‘image/jpeg’);

  32. gimly says:

    Thanks alot – great tutorial!

    @Sudarshan You can disable layout this way: $this->_helper->layout->disableLayout();

  33. Jyotsna says:

    Hi,

    Nice tutorial, thanks for sharing with us. I got it working. But the controller where I am using this is not recognizing the SESSION created in another (Image) controller.

    I got this error:
    Notice: Undefined index: captcha_code in C:AppServwwwsuper2controllersTestController.php on line 42

    Can you please help me to solve this problem.

    Thanks,
    Jyotsna.

  34. Wenbert says:

    @Jyotsa, make sure you have defined $_SESSION['captcha_code'].

    Try to do a $_SESSION['captcha_code'] = NULL;

    See if that works. If not, paste2.org your code and email me the link so that I can take a look at it.

  35. navdeep says:

    hi… i m unable to see the captcha image….
    no captcha code is here…..

    i just do thses things nothing else….
    1.
    my contoller:

    _helper->viewRenderer->setNoRender();
    }

    public function generatecaptchaAction()
    {

    //Let’s generate a totally random string using md5
    $md5_hash = md5(rand(0,999));
    //We don’t need a 32 character long string so we trim it down to 5
    $security_code = substr($md5_hash, 15, 5);

    $_SESSION['captcha_code'] = $security_code;

    //Set the image width and height
    $width = 100;
    $height = 20;

    //Create the image resource
    $image = ImageCreate($width, $height);

    //We are making three colors, white, black and gray
    $white = ImageColorAllocate($image, 255, 255, 255);
    $black = ImageColorAllocate($image, 0, 0, 0);
    $grey = ImageColorAllocate($image, 204, 204, 204);

    //Make the background black
    ImageFill($image, 0, 0, $black);

    //Add randomly generated string in white to the image
    ImageString($image, 3, 30, 3, $security_code, $white);

    //Throw in some lines to make it a little bit harder for any bots to break
    ImageRectangle($image,0,0,$width-1,$height-1,$grey);
    imageline($image, 0, $height/2, $width, $height/2, $grey);
    imageline($image, $width/2, 0, $width/2, $height, $grey);

    //Tell the browser what kind of file is come in
    header(“Content-Type: image/jpeg”);

    //Output the newly created image in jpeg format
    ImageJpeg($image);
    }
    }

    2: my view file:

    3: my form:

    Captcha Code:
    <img src=”baseUrl();?>/imagegenerator/generatecaptcha” />
    Enter Code Here:

    PLEASE HELP ME GUYS…..I am not having Captcha image….and sumbit button not working????

  36. Wenbert says:

    @navdeep try to var_dump the baseUrl(). make sure that works.
    You should see an image when you go to: http://mysite.com/imagegenerator/generatecaptcha

  37. Pingback: Zend Framework és Captcha – egyszerű céges oldal (Demo Kft) – Kapcsolat űrlap – biztonság IV.rész « Simon András blogja

  38. codeholic says:

    Nice code!I try this and it’s work fine in zf 1.5, but not work in zf 1.8. Can you give me a suggestion? Thanks !

  39. xDave says:

    hi, thnx for nice tutor, i got the same bug as some users here, in my case problem was that i use layout in my application. Here is updated init function() that solves that.

    public function init() {
    $this->_helper->layout->disableLayout();
    $this->_helper->viewRenderer->setNoRender();
    }

    You will know that you have the same problem, if you call your url of image (which now returns only title of url itself) in img html tag, then move the area which should be the image to your desktop, it will appear as html file, and when you open it,you can see bad bug content.

  40. jeuelc says:

    Thank you for this. It helped me a lot.

  41. lordave says:

    i have got the same problem
    to see ur captcha you must change header position like this

    public function generatecaptchaAction()
    {
    //Tell the browser what kind of file is come in
    header(“Content-Type: image/jpeg”);

    //Let’s generate a totally random string using md5
    $md5_hash = md5(rand(0,999));
    //We don’t need a 32 character long string so we trim it down to 5
    $security_code = substr($md5_hash, 15, 5);

    $_SESSION['captcha_code'] = $security_code;

    //Set the image width and height
    $width = 100;
    $height = 20;

    //Create the image resource
    $image = ImageCreate($width, $height);

    //We are making three colors, white, black and gray
    $white = ImageColorAllocate($image, 255, 255, 255);
    $black = ImageColorAllocate($image, 0, 0, 0);
    $grey = ImageColorAllocate($image, 204, 204, 204);

    //Make the background black
    ImageFill($image, 0, 0, $black);

    //Add randomly generated string in white to the image
    ImageString($image, 3, 30, 3, $security_code, $white);

    //Throw in some lines to make it a little bit harder for any bots to break
    ImageRectangle($image,0,0,$width-1,$height-1,$grey);
    imageline($image, 0, $height/2, $width, $height/2, $grey);
    imageline($image, $width/2, 0, $width/2, $height, $grey);

    //Output the newly created image in jpeg format
    ImageJpeg($image);
    }

  42. Mohammad Azhar Khan says:

    Great post Tomas!
    This is the simplest code to use Captcha..
    Sorry but you missed one line in function init():
    $this->_helper->layout()->disableLayout();
    Which make me worry for some hours! :)

  43. cong says:

    i think the code should add

    …………
    imagejpeg($image,null,75);
    imagedestroy($image);
    exit;
    }

Leave a Reply to Peter Hons Cancel reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>