Codeigniter – Create a CAPTCHA with Sessions using the Codeigniter’s Captcha helper

Now and then there is the need to create a captcha spam protection to stop spiders from spamming your website’s forms.

Codeigniter framework has a captcha helper that you can use if you already have GD library installed on the server.

I must admit I started my tutorial from this one: CodeIgniter Captcha & Session – How to by Example. That one is a good tutorial, but I will extend it with this one, because i find it more to my personal needs.

You must keep in mind that I will concentrate on the captcha part and will not make a full blown login system.

OK. Let’s start

You will firstly have to create a folder where the image will be saved. We will have to change its permission to 777 or 666. I named my folder ‘captcha’. Also, don’t forget to autoload the session library.

We will make a controller named login.php. Inside the controller we will create a private method named _create_captcha():

private function _create_captcha()
{
  // we will first load the helper. We will not be using autoload because we only need it here
  $this->load->helper('captcha');
  // we will set all the variables needed to create the captcha image
  $options = array('img_path'=>FCPATH.'captcha/','img_url'=>site_url().'captcha/','img_width'=>'150','img_height'=>'40','expiration'=>7200);
  //now we will create the captcha by using the helper function create_captcha()
  $cap = create_captcha($options);
  // we will store the image html code in a variable
  $image = $cap['image'];
  // ...and store the captcha word in a session
  $this->session->set_userdata('captchaword', $cap['word']);
  // we will return the image html code
  return $image;
}

As you saw, the options for creating the captcha code are only a few. On github you can find two versions of the helper: the stable version and the development one:

1. the stable version, 2.1-stable captcha helper (which is also the one that is found inside the stable version of Codeigniter), although is proven stable, is not that good because it lacks some things I need a captcha to have like font color, background color, number of characters. As you can see, the available options for creating the captcha code are: the word, the image path, the image url, the width of the image, the height of the image, the font path and the expiration value:

$defaults = array(‘word’ => ”, ‘img_path’ => ”, ‘img_url’ => ”, ‘img_width’ => ‘150’, ‘img_height’ => ’30’, ‘font_path’ => ”, ‘expiration’ => 7200)

2. the “under development” version, although it doesn’t guarantee stability, it has many options (as you can see the Codeigniter community is still very active). Those options, beside the ones you can find inside the stable version, are: word length, the pool from which the function can choose the characters, and the colors of the captcha image.

$defaults = array(‘word’ => ”, ‘img_path’ => ”, ‘img_url’ => ”, ‘img_width’ => ‘150’, ‘img_height’ => ’30’, ‘font_path’ => ”, ‘expiration’ => 7200, ‘word_length’ => 8, ‘pool’ => ‘0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ’, ‘colors’ => array( ‘background’ => array(255,255,255), ‘border’ => array(153,102,102), ‘text’ => array(204,153,153), ‘grid’ => array(255,182,182)).

After you created the _create_captcha() method, whenever you will call it, it will create a session variable called ‘captchaword‘ and will return you the captcha image needed for the form.

Now, to do it elegantly, we will also make a callback method to verify if the user entered the same captcha he/she saw in the image:

public function check_captcha($string)
{
  if($string==$this->session->userdata('captchaword'))
  {
    return TRUE;
  }
  else
  {
    $this->form_validation->set_message('check_captcha', 'Wrong captcha code');
    return FALSE;
  }
}

Let’s put it all together:

<?php if ( ! defined('BASEPATH')) exit('No direct script access allowed');

class Login extends CI_Controller
{
  private function _create_captcha()
  {
    // we will first load the helper. We will not be using autoload because we only need it here
    $this->load->helper('captcha');
    // we will set all the variables needed to create the captcha image
    $options = array('img_path'=>FCPATH.'captcha/','img_url'=>site_url().'captcha/','img_width'=>'150','img_height'=>'40','expiration'=>7200);
    //now we will create the captcha by using the helper function create_captcha()
    $cap = create_captcha($options);
    // we will store the image html code in a variable
    $image = $cap['image'];
    // ...and store the captcha word in a session
    $this->session->set_userdata('captchaword', $cap['word']);
    // we will return the image html code
    return $image;
  }

  public function check_captcha($string)
  {
    if($string==$this->session->userdata('captchaword'))
    {
      return TRUE;
    }
    else
    {
      $this->form_validation->set_message('check_captcha', 'Wrong captcha code');
      return FALSE;
    }
  }

  public function index()
  {
    //whenever someone gets to the login page we will create a captcha and render the login form
    $data['image']=$this->_create_captcha();
    $this->load->view('login_form_view',$data);
  }
  // we will also create a method to verify the data that the user has entered

  public function verify()
  {
    //we will check the form completion and verify the credentials such as the username, email or password. I will jump over that part and concentrate on the captcha part...
    $this->form_validation->set_rules( 'captcha', 'captcha', 'trim|callback_check_captcha|required' );
    //as you can see, I used the check_captcha callback to verify if the characters the user entered are the same as the ones that can be found inside the captcha image
    if($this->form_validation->run()===false) /* if the form validation failed */
    {
      $data['image']=$this->_create_captcha(); /* we will again call the captcha creator to recreate the captcha an the image */
      $this->load->view('login_view',$data); /* and load the login_view */
    }
    else
    {
      // from here on we can do whatever we want if the form validation was passed
    }
  }
}

Now the login_view.php will look as below:

<form action="login/verify" method="post">
<!-- the form elements you need followed by the captcha image and the captcha form element-->
<input type="text" name="word" />
<?php echo $image; // this will show the captcha image?>
<input type="submit" name="submit" value="submit" />
</form>

Important note:

Verify if the captcha code is shown everytime on the image. There are times when the image doesn’t show the full captcha code because the image’s width is not big enough, especially if you chose a particular font. The increase of the image’s width was the only solution for the stable version of the helper to work properly. One of the reasons I chose to work with the “under development” version of the helper instead of the stable version is that with that version you can also choose the number of characters that the captcha code must have (I think a captcha code with 4 to 5 characters is more than enough).

9 comments

  1. i need captcha image file which is in captcha folder. Pls help if you have that files which are present in captcha folder.

  2. Cute and simple workaround for the codeigniter build-in captcha helper.
    I would like to point out one small bug in using session name: you first declare it using session key “captchaword” and then, in callback check function, you compare the user input with another session key “word”. Debug that and should work.
    Also, if you like keeping framework forks (like this one) as a start base-pack for new projects (as I like to do), you could replace the options for captcha images with something like that:
    $options = array('img_path'=>FCPATH.'captcha/','img_url'=> site_url().'captcha/','expiration'=>7200);
    or even replace’it in helper to be taken as default.

  3. i got this error “Fatal error: Maximum execution time of 30 seconds exceeded in /home/noushi/projects/psybo/system/helpers/captcha_helper.php on line 174”
    how can solve it?

    1. Hello, again. It seems that what happend in there was a CodeIgniter bug, which was fixed today: “Fixed a bug where CAPTCHA Helper entered an infinite loop while generating a random string.”. You need to update to CodeIgniter 3.0.4

  4. First of all thank you for sharing this informative blog.. This blog having more useful information that information explanation are step by step and very clear so easy and interesting to read.. After reading this blog i am strong in this topic which helpful to cracking the interview easily…

Leave a Reply

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

No spam? * Time limit is exhausted. Please reload CAPTCHA.