CakePHP 2.6 Auth CAPTCHA Example (BotDetect v3.0; deprecated)

This example demonstrates how to integrate BotDetect PHP Captcha into login and register forms in a scenario where CakePHP Auth Component is used to authenticate users to your application.

First Time Here?

Check the BotDetect CakePHP 2.6 Captcha Quickstart for key integration steps.

When CakePHP Auth Component is turned on in your application, it requires you to use database. Here is how to create it:

For purpose of this example, we'll use the database file included in a BotDetect Captcha CakePHP integration package.

The database file is located at: /bd-captcha-cakephp-2.6-examples/database/ cakephp_auth.sql.

The next step is to configure connection to your database by entering connection details in the <MYCAKEAPP>/Config/database.php file.

Files for this example are:

The files are available for download as a part of the BotDetect Captcha CakePHP integration package.

View – /app/View/Users/login.ctp

<?php 
// include the BotDetect layout stylesheet
echo $this->Html->css(CaptchaUrls::LayoutStylesheetUrl(), array('inline' => false));
?>

<div class="users form">
<?php echo $this->Form->create('User'); ?>
  <fieldset>
    <legend><?php echo __('Login'); ?></legend>
  <?php
    echo $this->Form->input('username');
    echo $this->Form->input('password');
	
     // display Captcha markup, wrapped in an extra div for layout purposes
      echo $this->Html->div('captcha', $captchaHtml, false);

      // Captcha code user input textbox
      echo $this->Form->input('CaptchaCode', array(
              'label' => 'Retype the characters from the picture:',
              'maxlength' => '10',
              'style' => 'width: 300px; text-transform: uppercase;'
          )
      );
  ?>
  </fieldset>
<?php 
  echo $this->Form->end(__('Submit')); 
  echo 'or ' . $this->Html->link('Register', array('controller' => 'users', 'action' =>
  'add'));
?>
</div>

<div class="actions">
  <h3><?php echo __('The default login is:'); ?></h3>
  Username: administrator
  Password: password
</div>

The above code is used to create CakePHP FormHelper. To display authentication in a view, we output the variable $captchaHtml (set in, and passed by in the login() method of UsersController).

Also we have added Captcha Code input field to view. This Captcha Code input will be checked in the login() method later.

To display correctly, BotDetect Captcha PHP requires you to include its CSS. We have used HtmlHelper::css() to create a link to the CSS file.

View – /app/View/Users/add.ctp

<?php 
  if (!$logged_in) {
    // include the BotDetect layout stylesheet
      echo $this->Html->css(CaptchaUrls::LayoutStylesheetUrl(), array('inline' => 
      false));
    }
?>

<div class="users form">
<?php echo $this->Form->create('User'); ?>
  <fieldset>
    <legend><?php echo __('Register'); ?></legend>
  <?php
    echo $this->Form->input('name');
    echo $this->Form->input('username');
    echo $this->Form->input('password');
    echo $this->Form->input('password_confirmation', array('type' => 'password'));
    echo $this->Form->input('email');

    if ($logged_in && $is_admin) {
      echo $this->Form->input('role', array(
              'options' => array('admin' => 'Admin', 'author' => 'Author')
          ));
    }

    if (!$logged_in) {
      // display Captcha markup, wrapped in an extra div for layout purposes
        echo $this->Html->div('captcha', $captchaHtml, false);

        // Captcha code user input textbox
        echo $this->Form->input('CaptchaCode', array(
                'label' => 'Retype the characters from the picture:',
                'maxlength' => '10',
                'style' => 'width: 300px; text-transform: uppercase;'
            )
        );
    }
  ?>
  </fieldset>
<?php echo $this->Form->end(__('Submit')); ?>
</div>
<div class="actions">
  <h3><?php echo __('Actions'); ?></h3>
  <ul>

    <li><?php echo $this->Html->link(__('List Users'), array('action' => 'index')); ?><
    /li>
  </ul>
</div>

The above code is used to create CakePHP FormHelper. To display authentication in a view, we output the variable $captchaHtml (set in, and passed by in the add() method of UsersController).

Also we have added Captcha Code input field to view. This Capthca Code input will be checked in the add() method later.

To display correctly, BotDetect Captcha PHP requires you to include its CSS. We have used HtmlHelper::css() to create a link to the CSS file.

Controller – /app/Controller/UsersController.php

<?php
App::uses('AppController', 'Controller');

class UsersController extends AppController {

  public $components = array(
    'Paginator',
    // load the BotDetect Captcha component and set its parameters
    'BotDetect.Captcha' => array(
        'CaptchaId' => 'AuthCaptcha', // a unique Id for the Captcha instance
          'UserInputId' => 'CaptchaCode' // Id of the Captcha code input textbox
      )
  );

  public function isAuthorized($user) {
    if (isset($user['role']) && $user['role'] === 'admin') {
          return true;
      }
  
        if (in_array($this->action, array('edit', 'delete'))) {
          if ($this->request->params['pass'][0] == $user['id']) {
            return true;
          }
        }
        return false;
    }

  public function beforeFilter() {
        parent::beforeFilter();
        $this->Auth->allow('add');

        $this->Security->validatePost = false;
    }

  public function login() {
    // make Captcha Html accessible to View code
      $this->set('captchaHtml', $this->Captcha->Html());

      if ($this->request->is('post')) {
        // validate the user-entered Captcha code
      $code = $this->request->data['User']['CaptchaCode'];
      $isHuman = $this->Captcha->Validate($code);

      // clear previous user input, since each Captcha code can only be validated once
      unset($this->request->data['User']['CaptchaCode']);

      if ($isHuman && $this->Auth->login()) {
        // Captcha validation passed and login successful
        return $this->redirect($this->Auth->redirectUrl());
      } else {
        if (!$isHuman) {
          // Captcha validation failed, return an error message
          $this->Session->setFlash(__('CAPTCHA validation failed, try again.'));
        } else {
          $this->Session->setFlash(__('Invalid username or password, try again'));
        }
      }
    }
  }

  public function logout() {
    return $this->redirect($this->Auth->logout());
  }

  public function index() {
    $this->User->recursive = 0;
    $this->set('users', $this->Paginator->paginate());
  }

  public function view($id = null) {
    if (!$this->User->exists($id)) {
      throw new NotFoundException(__('Invalid user'));
    }
    $options = array('conditions' => array('User.' . $this->User->primaryKey => $id));
    $this->set('user', $this->User->find('first', $options));
  }

  public function add() {
    // not show and validate captcha when logged in
    if ($this->Auth->loggedIn()) {
      
      if ($this->request->is('post')) {
        $this->User->create();
        if ($this->User->save($this->request->data)) {
          // Captcha validation passed and save successful
          $this->Session->setFlash(__('The user has been saved.'));
          return $this->redirect(array('action' => 'index'));
        } else {
          $this->Session->setFlash(__('The user could not be saved. Please, try again.
          '));
        }
      }

    } else {
      // make Captcha Html accessible to View code
        $this->set('captchaHtml', $this->Captcha->Html());

        if ($this->request->is('post')) {
        // validate the user-entered Captcha code
        $code = $this->request->data['User']['CaptchaCode'];
        $isHuman = $this->Captcha->Validate($code);

        // clear previous user input, since each Captcha code can only be validated once
        unset($this->request->data['User']['CaptchaCode']);

        $this->User->create();
        if ($isHuman && $this->User->save($this->request->data)) {
          // Captcha validation passed and save successful
          $this->Session->setFlash(__('The user has been saved.'));
          return $this->redirect(array('action' => 'index'));
        } else {
          if (!$isHuman) {
            // Captcha validation failed, return an error message
            $this->Session->setFlash(__('CAPTCHA validation failed, try again.'));
          } else {
            $this->Session->setFlash(__('The user could not be saved. Please, try 
            again.'));
          }
        }
      }
    }
  }

  public function edit($id = null) {
    if (!$this->User->exists($id)) {
      throw new NotFoundException(__('Invalid user'));
    }
    if ($this->request->is(array('post', 'put'))) {
      if ($this->User->save($this->request->data)) {
        $this->Session->setFlash(__('The user has been saved.'));
        return $this->redirect(array('action' => 'index'));
      } else {
        $this->Session->setFlash(__('The user could not be saved. Please, try again.'))
        ;
      }
    } else {
      $options = array('conditions' => array('User.' . $this->User->primaryKey => $id))
      ;
      $this->request->data = $this->User->find('first', $options);
    }
  }

  public function delete($id = null) {
    $this->User->id = $id;
    if (!$this->User->exists()) {
      throw new NotFoundException(__('Invalid user'));
    }
    $this->request->allowMethod('post', 'delete');
    if ($this->User->delete()) {
      $this->Session->setFlash(__('The user has been deleted.'));
    } else {
      $this->Session->setFlash(__('The user could not be deleted. Please, try again.'))
      ;
    }
    return $this->redirect(array('action' => 'index'));
  }
}

The example Controller follows the basic instructions from the BotDetect CakePHP 2.6 integration guide.

Loading the required helpers and creating the BotDetect Captcha.

Method: login()

The Html required for displaying the Captcha image and integrated controls is made available to the View by using the Controller:set() method.

The example form submits data to the same Controller action that shows it (login). This is where we check the submitted captcha code and pass it to the Validate() method of the Captcha component object.

Method: add()

The Html required for displaying the Captcha image and integrated controls is made available to the View by using the Controller:set() method.

The example form submits data to the same Controller action that shows it (add). This is where we check the submitted captcha code and pass it to the Validate() method of the Captcha component object.

Captcha is hidden and validation doesn't occur for users that are already logged in.



Please Note

The information on this page is out of date and applies to a deprecated version of BotDetect™ CAPTCHA (v3.0).

An up-to-date equivalent page for the latest BotDetect Captcha release (v4) is BotDetect v4 Captcha documentation index.

General information about the major improvements in the current BotDetect release can be found at the What's New in BotDetect v4.0 page.