Captcha component with Securimage

This article is also available in the following languages:
By debuggeddesigns
Securimage is an open-source free PHP CAPTCHA script for generating complex images and CAPTCHA codes to protect forms from spam and abuse. It can be easily added into existing forms on your website to provide protection from spam bots. It can run on most any webserver as long as you have PHP installed, and GD support within PHP. Securimage does everything from generate complicated CAPTCHA images to making sure the code the user entered was correct.

Securimage Features

  • Show an image in just 3 lines of code
  • Validate submitted entries in less than 6 lines of code
  • Customizable code length
  • Choose the character set
  • TTF font support
  • Use custom GD fonts when TTF is not available
  • Easily add background images
  • Multi colored, angled, and transparent text options
  • Arched lines through text
  • Generates audible CAPTCHA files in wav format
  • Use a word list for creating CAPTCHA codes

Step 1: Download and unzip Securimage archive

Download a Securimage archive (either .zip or .tar.gz) at http://www.phpcaptcha.org/download/ and unzip the archive into the directory /app/vendors/securimage/


Step 2: Create captcha component

Filename: /app/controllers/components/captcha.php

Component Class:

<?php 

/**
 * Securimage-Driven Captcha Component
 * @author debuggeddesigns.com
 * @license MIT
 * @version 0.1
 */
 
//cake's version of a require_once() call
vendor('securimage'.DS.'securimage'); //use this with the 1.1 core
//App::import('Vendor','Securimage' ,array('file'=>'securimage'.DS.'securimage.php')); //use this with the 1.2 core
  
 
//the local directory of the vendor used to retrieve files
define('CAPTCHA_VENDOR_DIR'APP 'vendors' DS 'securimage/');

class 
CaptchaComponent extends Object {

    var 
$controller;

    
//size configuration
    
var $_image_height 75//the height of the captcha image
    
var $_image_width 350//the width of the captcha image
    
    
    //background configuration
    
var $_draw_lines true//whether to draw horizontal and vertical lines on the image
    
var $_draw_lines_over_text false//whether to draw the lines over the text
    
var $_draw_angled_lines true//whether to draw angled lines on the image
    
    
var $_image_bg_color '#ffffff'//the background color for the image
    
var $_line_color '#cccccc'//the color of the lines drawn on the image
    
var $_line_distance 15//how far apart to space the lines from eachother in pixels
    
var $_line_thickness 2//how thick to draw the lines in pixels
    
var $_arc_line_colors '#999999,#cccccc'//the colors of arced lines
    
    
    //text configuration
    
var $_use_gd_font false//whether to use a gd font instead of a ttf font
    
var $_use_multi_text true//whether to use multiple colors for each character
    
var $_use_transparent_text true//whether to make characters appear transparent
    
var $_use_word_list false//whether to use a word list file instead of random code
    
    
var $_charset 'ABCDEFGHKLMNPRSTUVWYZ23456789'//the character set used in image
    
var $_code_length 5//the length of the code to generate
    
var $_font_size 45//the font size
    
var $_gd_font_size 50//the approxiate size of the font in pixels
    
var $_text_color '#000000'//the color of the text - ignored if $_multi_text_color set
    
var $_multi_text_color '#006699,#666666,#333333'//the colors of the text
    
var $_text_transparency_percentage 45//the percentage of transparency, 0 to 100
    
var $_text_angle_maximum 21//maximum angle of text in degrees
    
var $_text_angle_minimum = -21//minimum angle of text in degrees
    
var $_text_maximum_distance 70//maximum distance for spacing between letters in pixels
    
var $_text_minimum_distance 68//minimum distance for spacing between letters in pixels
    
var $_text_x_start 10//the x-position on the image where letter drawing will begin
    
    
    //filename and/or directory configuration
    
var $_audio_path 'audio/'//the full path to wav files used
    
var $_gd_font_file 'gdfonts/bubblebath.gdf'//the gd font to use
    
var $_ttf_file 'elephant.ttf'//the path to the ttf font file to load
    
var $_wordlist_file 'words/words.txt'//the wordlist to use
    
    
    
function startup( &$controller ) {

        
//add local directory name to paths
        
$this->_ttf_file CAPTCHA_VENDOR_DIR.$this->_ttf_file
        
$this->_gd_font_file CAPTCHA_VENDOR_DIR.$this->_gd_font_file;
        
$this->_audio_path CAPTCHA_VENDOR_DIR.$this->_audio_path;
        
$this->_wordlist_file CAPTCHA_VENDOR_DIR.$this->_wordlist_file
        
//CaptchaComponent instance of controller is replaced by a securimage instance
        
$controller->captcha =& new securimage();
        
$controller->captcha->arc_line_colors $this->_arc_line_colors;
        
$controller->captcha->audio_path $this->_audio_path;
        
$controller->captcha->charset $this->_charset;
        
$controller->captcha->code_length $this->_code_length;
        
$controller->captcha->draw_angled_lines $this->_draw_angled_lines;
        
$controller->captcha->draw_lines $this->_draw_lines;
        
$controller->captcha->draw_lines_over_text $this->_draw_lines_over_text;
        
$controller->captcha->font_size $this->_font_size;
        
$controller->captcha->gd_font_file $this->_gd_font_file;
        
$controller->captcha->gd_font_size $this->_gd_font_size;
        
$controller->captcha->image_bg_color $this->_image_bg_color;
        
$controller->captcha->image_height $this->_image_height;
        
$controller->captcha->image_width $this->_image_width;
        
$controller->captcha->line_color $this->_line_color;
        
$controller->captcha->line_distance $this->_line_distance;
        
$controller->captcha->line_thickness $this->_line_thickness;
        
$controller->captcha->multi_text_color $this->_multi_text_color;
        
$controller->captcha->text_angle_maximum $this->_text_angle_maximum;
        
$controller->captcha->text_angle_minimum $this->_text_angle_minimum;
        
$controller->captcha->text_color $this->_text_color;
        
$controller->captcha->text_maximum_distance $this->_text_maximum_distance;
        
$controller->captcha->text_minimum_distance $this->_text_minimum_distance;
        
$controller->captcha->text_transparency_percentage $this->_text_transparency_percentage;
        
$controller->captcha->text_x_start $this->_text_x_start;
        
$controller->captcha->ttf_file $this->_ttf_file;
        
$controller->captcha->use_gd_font $this->_use_gd_font;
        
$controller->captcha->use_multi_text $this->_use_multi_text;
        
$controller->captcha->use_transparent_text $this->_use_transparent_text;
        
$controller->captcha->use_word_list $this->_use_word_list;
        
$controller->captcha->wordlist_file $this->_wordlist_file;
        
$controller->set('captcha',$controller->captcha);
    }
}

?>


Step 3: Use the captcha component inside a controller

Filename: /app/controllers/contacts_controller.php

Controller Class:

<?php 

class ContactsController extends AppController {
    
    var 
$name 'Contacts';
    var 
$components = array('Captcha');
     
    function 
securimage($random_number){
        
$this->autoLayout false//a blank layout

        //override variables set in the component - look in component for full list
        
$this->captcha->image_height 75;
        
$this->captcha->image_width 350;
        
$this->captcha->image_bg_color '#ffffff';
        
$this->captcha->line_color '#cccccc';
        
$this->captcha->arc_line_colors '#999999,#cccccc';
        
$this->captcha->code_length 5;
        
$this->captcha->font_size 45;
        
$this->captcha->text_color '#000000';

        
$this->set('captcha_data'$this->captcha->show()); //dynamically creates an image
    
}

    function 
index(){
        
$this->set('captcha_form_url'$this->webroot.'contacts/index'); //url for the form
        
$this->set('captcha_image_url'$this->webroot.'contacts/securimage/0'); //url for the captcha image

        
$captcha_success_msg 'The code you entered matched the captcha';
        
$captcha_error_msg 'The code you entered does not match';

        if( empty(
$this->data) ){ //form has not been submitted yet
            
$this->set('error_captcha'''); //error message displayed to user
            
$this->set('success_captcha'''); //success message displayed to user
            
$this->render(); //reload page
        
} else { //form was submitted     
            
if( $this->captcha->check($this->data['Contact']['captcha_code']) == false ) {
                
//the code was incorrect - display an error message to user
                
$this->set('error_captcha'$captcha_error_msg); //set error msg
                
$this->set('success_captcha'''); //set success msg
                
$this->render(); //reload page
            
} else {
                
//the code was correct - display a success message to user
                
$this->set('error_captcha'''); //set error msg
                
$this->set('success_captcha'$captcha_success_msg); //set success msg
                
$this->render(); //reload page

                //after testing is complete, you would process the other form data here and save it
            
}
        }
    }
}

?>


Step 4: Create a Contact model

Filename: /app/models/contact.php

View Template:


<?php
class Contact extends AppModel {
   var 
$useTable false;
}
?> 


Step 5: Create a view to hold the dynamic image

Filename: /app/views/contacts/securimage.thtml

View Template:


<?php echo $captcha_data?>


Step 6: Create a view to test the captcha with

Filename: /app/views/contacts/index.thtml

View Template:


<form action="<?php echo $captcha_form_url?>" method="post">
<div>Verify :</div>
<div><img src="<?php echo $captcha_image_url?>" id="captcha" alt="CAPTCHA Image" /></div>
<div><input type="text" name="data[Contact][captcha_code]" size="10" maxlength="6" value="" /></div>
<div><a href="#" onclick="document.getElementById('captcha').src = '<?php echo $this->webroot;?>contact/securimage/' + Math.random(); return false">Reload Image</a></div>
<div style="color:red;"><?php echo $error_captcha?></div>
<div style="color:green;"><?php echo $success_captcha?></div>
<div><input type="submit" value="CLICK HERE TEST THE CAPTCHA" /></div>
</form>

Comments

  • Posted 05/28/11 02:16:44 AM
    A known and un-patched authentication bypass exists with PHPCaptcha, use the CAPTCHA library with caution:

    http://www.idontplaydarts.com/2011/05/exploit-phpcaptcha-securimage/
  • Posted 01/18/11 04:33:04 PM
  • Posted 08/30/10 05:09:04 AM
    Hi
    In my component I am using
    $controller->captcha->show("/images/code_bg.gif");

    for my own image as a captcha background but it is not working anybody have the solution please help.

  • Posted 08/13/10 11:20:10 AM
    does anyone try this with 1.3?
    • Posted 09/01/10 03:55:36 AM
      does anyone try this with 1.3?
      Yes and it work !
  • Posted 08/11/10 02:19:57 AM
    Hello All,

    I am using Captcha component in users controller. I am using isConfigure() function of users controller in homes controller.
    function isConfigure() {


    if ($this->Auth->user()){
    ......
    return true;
    }
    else
    return false;
    }
    Its working fine if i use $component=array('Captcha',...) in homes controller. Why we need Captcha components in homes controller? Please help....
  • Posted 08/10/10 05:40:24 PM
    I don't see any error and I can't display captcha img.
    Only showing alt, "CAPTCHA Image", and when I check sorce src value is src="/contacts/securimage/0"

    I'm using 1.3 and inside of captcha.php

    //vendor('securimage'.DS.'securimage'); //use this with the 1.1 core 
    App::import('Vendor','Securimage' ,array('file'=>'securimage'.DS.'securimage.php')); //use this with the 1.2 core


    I'm not sure issue is with 1.3 but I read so many times install steps and comments and nothing can fix my issues. Does anyone try with 1.3?



  • Posted 02/19/10 07:49:22 AM
    Thank you for sharing.
  • Posted 11/02/09 07:03:26 AM
    i got cake 1.2, installed vendor and done everything as in tutorial. but it generates image without letters
    http://gkrb.ufa-arenda.ru/contacts/securimage/0.453563
    i have tried numerous settings but none of them worked. if i run bundled securimage_example.php, it works ok.
  • Posted 08/20/09 04:23:59 PM
    When I load the Cookie component in my app_controller.php, the captcha image dont change if I refresh de URL.


    class AppController extends Controller {
    var $components = array('Session', 'Cookie');
    /*
    .
    .
    .
    .
    */
    ?>
    class CaptchasController extends AppController {
    var $name = 'Captchas';
    var $uses = array();
    var $components = array('Captcha');

    /*
    .
    .
    .
    .
    */
    ?>
    Please need some help
  • Posted 07/21/09 01:56:25 AM
    I have tried writing one. However I have been unsuccessful. I face errors with "$this->captcha->check($this->data['User']['captcha_code'])"

    Hello,

    i have same problem that Nikhil has already stated here. I am trying to put all form errors in one place so they stay at the same level. I have several custom validation functions that i call in model with $validate array but the problem occures when im trying to bring that captcha validation into my model rather than keeping it in controller. since the check() function is the Securimage class i dont feel like moding it. maybe there is way to call for it from my model. or is there any workarounds in general just to keep form and captcha errors together.
  • Posted 07/21/09 01:47:54 AM
    Hello,
    I have tried writing one. However I have been unsuccessful. I face errors with "$this->captcha->check($this->data['User']['captcha_code'])"

    Nikhil actually stated the problem i have with putting validation script inside model rather than having it in controller for the sake of keeping error messages together in one place. im validating many things with custom validation functions and i wanted to keep the captcha validation on the same level as those or even lower, which as i can figure can be done by putting the validation function in same place with others. The problem occurs with check() function which is located in Securimage class. I'm not really into moding the securimage classes or files but i can't figure out how could i make the call for that function inside my model.

    Any help would be more than welcome.
    Thanks
  • Posted 07/20/09 01:26:12 PM
    Had problems making it work initially but it worked..Thanks for this cool component..btw I am an absolute beginner..:)
  • Posted 07/17/09 12:00:16 AM
    I have a problem to show the image.

    The image “/Path/to/controller/action” cannot be displayed, because it contains errors.

    I turned off display_errors and uninstall the plugin for skype, and $_use_gd_font=true. It shows like that too.

    Any ideas?
  • Posted 07/13/09 05:07:50 AM
    Hello,

    Thanks for the app.zip file providation, it helped me a lot to find out the solution and make Captcha working properly.

    Keep up sharing good codes!

    Thanks,

    Aditya Bhatt
  • Posted 05/18/09 12:49:46 PM
    http://www.debuggeddesigns.com/files/app.zip
    this app configuration uses the latest cake release and has the latest secure image download... hope this helps
  • Posted 05/15/09 08:08:58 AM
    I also encounter this error. Can anybody help?

    Warning: session_start() [function.session-start]: Cannot send session cache limiter - headers already sent (output started at D:\MySiteapp\controllers\components\captcha.php:109) in D:\MySite\app\vendors\securimage\securimage.php on line 422...

    If I will comment the session_start() (at securimage.php), it will not display the error but still the image will not display...

    By the way, it would be better if you send us a sample working script using the cakephp.. :).. Please help the junins!!! :)
  • Posted 05/12/09 04:16:35 PM
    This worked in 5 mins, Thank you !!

    Controller name is mistyped the index view at Reload Image:

    webroot;?>contact/securimage/

    should be contacts


    Thanks,

    Andras
  • Posted 04/13/09 08:27:11 AM
    Hello...

    Thanks for this useful tutorial. I have used it in my user registration form and it works like charm. However I have one doubt. (Apologies if this question is felt to be slightly off topic)

    I use the model to validate the rest of the fields of the registration form i.e by defining an array $ validates. I wanted my captcha to also work through the model (using a function) rather than the controller as described by this example.

    I have tried writing one. However I have been unsuccessful. I face errors with "$this->captcha->check($this->data['User']['captcha_code'])"

    I am unable to get captcha->check to work in the model... any help with reg to same will be appreciated...

    regards
    nikhil
  • Posted 04/08/09 01:03:54 PM
    It's work now thanks ...
  • Posted 04/07/09 11:44:04 AM
    First thanks for this useful tutorials ..

    I have 2 problem when excute :

    first one :
    Warning (2): session_start() [function.session-start]: Cannot send session cache limiter - headers already sent (output started at C:\xampp\htdocs\cakephp\app\controllers\contacts_controller.php:53) [APP\vendors\securimage\securimage.php, line 422]
    second the image not display

    Any idea .... Thank
    • Posted 04/07/09 04:16:01 PM
      First thanks for this useful tutorials ..

      I have 2 problem when excute :

      first one :
      Warning (2): session_start() [function.session-start]: Cannot send session cache limiter - headers already sent (output started at C:\xampp\htdocs\cakephp\app\controllers\contacts_controller.php:53) [APP\vendors\securimage\securimage.php, line 422]
      second the image not display

      Any idea .... Thank

      Do you have any white spaces outside the php tags in your controller class? When I copy the contacts_controller code into my SDK I always have a trailing extra line at the end.

  • Posted 03/24/09 04:55:36 AM
    Hi, after installing I had a problem: the image was not displayed.
    I have added in contacts_controller.php before the line
    $this->set('captcha_data', $this->captcha->show()); //dynamically creates an image 
    the function
    ob_clean(); to cleaning output buffer.
    Now it works perfect. Thanks for the code, it is very useful.
  • Posted 03/11/09 07:58:51 AM
    HI,

    everything works fine but: when i reload the page, the same letters are displayed. I thought everytime the page is reloaded or the user captcha code is false, an another word will be displayed. I have the word list in an Words - Folder, and i runned the server_test file and everything looks ok
    Need some help with that.

    Thanks
    • Posted 03/14/09 08:35:26 AM
      HI,

      everything works fine but: when i reload the page, the same letters are displayed. I thought everytime the page is reloaded or the user captcha code is false, an another word will be displayed. I have the word list in an Words - Folder, and i runned the server_test file and everything looks ok
      Need some help with that.

      Thanks

      That's a bug in some PHP versions. Yo should replace all the instances to "rand(xxxx,xxxx)" function in the file secureimage.php by "mt_rand(xxxx,xxxx)". This worked for me.
      • Posted 04/07/09 03:14:33 AM
        Hi Igor,

        thanks a lot man, this has resolved my problem!

        Flowreen
  • Posted 02/18/09 11:29:59 PM
    I added a reload button that uses javascript to update the image. I also added the Contact model and removed the blank view.
  • Posted 02/09/09 07:43:26 PM
    For noobs like me who are getting an error that it can't find the Contact table:

    Create /app/models/contact.php:

    <?php

    class Contact extends AppModel {
       var 
    $useTable false;
    }

    ?>


    Once I did this the demo worked perfectly with no other changes.
  • Posted 01/17/09 06:51:57 AM
    Instead of using blank layout, if you set $this->autoLayout to false in controller's action then it will just return current page's content (not with layout content)
  • Posted 12/30/08 03:46:34 PM
    I've installed as described on the page and when going to my Captcha test page the Captcha image is not being displayed. Only the "alt" image is shown. Doing a 'view source' shows that img src is blank (i.e. img src=""). I've double-checked the "captcha_image_url" in the contacts_controller.php file and even tried to modify it, but I can't seem to get the img src url inserted.

    Anyone have any ideas what I'm doing wrong?
    • Posted 01/12/09 08:56:18 PM
      I've installed as described on the page and when going to my Captcha test page the Captcha image is not being displayed. Only the "alt" image is shown. Doing a 'view source' shows that img src is blank (i.e. img src=""). I've double-checked the "captcha_image_url" in the contacts_controller.php file and even tried to modify it, but I can't seem to get the img src url inserted.

      Anyone have any ideas what I'm doing wrong?

      Hello, if you are using the 1.2 version be sure that you change the line in the component:
      //App::import('Vendor','Securimage' ,array('file'=>'securimage/securimage.php')); //use this with the 1.2 core  you have to uncomment that line and comment the other one.
      Second be sure that you are using all the call to the controller well, if you have your own controller like users change contacts to user.
      Third if you have a Auth component you have to add this actions ('index', 'securimage') to the allow. pd: index change for your action.
          function beforeFilter(){
              $this->Auth->allow('signup', 'home', 'update_select', 'confirm', 'index', 'securimage');
          }
      something like that could be.
      good luck.
      • Posted 07/20/09 01:15:25 PM
        Where are you putting your secureimage folder ?.It should be put in the app/vendors/ folder and not the vendors folder in the root directory.I had a similar problem and it solved by moving the folder into the inner vendors directory.Hope this helps..

        I've installed as described on the page and when going to my Captcha test page the Captcha image is not being displayed. Only the "alt" image is shown. Doing a 'view source' shows that img src is blank (i.e. img src=""). I've double-checked the "captcha_image_url" in the contacts_controller.php file and even tried to modify it, but I can't seem to get the img src url inserted.

        Anyone have any ideas what I'm doing wrong?

        Hello, if you are using the 1.2 version be sure that you change the line in the component:
        //App::import('Vendor','Securimage' ,array('file'=>'securimage/securimage.php')); //use this with the 1.2 core  you have to uncomment that line and comment the other one.
        Second be sure that you are using all the call to the controller well, if you have your own controller like users change contacts to user.
        Third if you have a Auth component you have to add this actions ('index', 'securimage') to the allow. pd: index change for your action.
            function beforeFilter(){
                $this->Auth->allow('signup', 'home', 'update_select', 'confirm', 'index', 'securimage');
            }
        something like that could be.
        good luck.
  • Posted 12/22/08 08:32:31 PM
    This component installed like a piece of cake!

    Looks great to.

    Well I got it up and running with no problems but I'd like to add the reload button. I cant seem to find the function for it. Any one figured this one out?

    Thanks!

    justclint
  • Posted 11/21/08 01:23:54 AM
    Hi Mike,

    Have you tried using a gd font? ($_use_gd_font var in captcha.php)
    Or made sure the code length is > 1? ($_code_length var in captcha.php)
    Or made sure the font files exist in the vendors/securimage directory? ($_gd_font_file and $ttf_file vars in captcha.php)

    Yes, I probably should have used .ctp - the .thtml extension was used in the cake 1.1 core - old habits.

    Hope that helped.
    • Posted 05/12/09 02:22:43 AM
      Hi, I got the same problem as Mike. I've tried everything you mentioned in last reply, but they didn't work. The output of securimage.thtml was something like "‰PNG  ��� IHDR���¯". It looks like that's the binary code of the image. Please help.


      Hi Mike,

      Have you tried using a gd font? ($_use_gd_font var in captcha.php)
      Or made sure the code length is > 1? ($_code_length var in captcha.php)
      Or made sure the font files exist in the vendors/securimage directory? ($_gd_font_file and $ttf_file vars in captcha.php)

      Yes, I probably should have used .ctp - the .thtml extension was used in the cake 1.1 core - old habits.

      Hope that helped.
  • Posted 11/06/08 09:29:26 AM
    Thanks a lot mate! It works like charm!
  • Posted 10/28/08 10:39:50 AM
    Hi, is it possible to reload the generated captcha image via an ajax-link in the view? I've tried without success..
  • Posted 10/22/08 05:16:57 AM
    Hi,

    Thanks for the code but I can't get the CAPTCHA image to show any characters. All I see in the image is a couple of arc lines. Any ideas what the problem is?

    Also, shouldn't the views in Steps 4-6 have the .CTP extension?

Comments are closed for articles over a year old