How to Add BotDetect PHP CAPTCHA Protection to CakePHP 3 Applications

Adding BotDetect PHP Captcha protection to your CakePHP MVC applications requires a slightly different approach than adding it to basic PHP websites, but is still straightforward. This page will guide you through the necessary steps and explain the available options.

First Time Here?

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

Prerequisites

Table of Contents

The BotDetect CakePHP CAPTCHA Integration Package

CakePHP is a MVC framework that leverages certain conventions to provide a rich set of functionality to PHP application developers. Therefore adding BotDetect Captcha into CakePHP based site or application requires a layer of integration code to conform to those conventions. This enables BotDetect Captcha to integrate seamlessly and be used according to expectations of CakePHP developers.

Path Aliases Used Throughout This Guide

For convenience purposes we are providing the BotDetect Captcha CakePHP integration code packaged as a CakePHP composer plugin.

You can get the whole BotDetect CakePHP Captcha integration package here. The package contains the integration code, basic Captcha validation example, an example demonstrating the usage of the BotDetect Captcha with CakePHP Validation and FormHelper. There is also an example of adding BotDetect Captcha into CakePHP Auth Login and Register forms.

The BotDetect CakePHP CAPTCHA Composer Plugin

BotDetect CakePHP CAPTCHA composer plugin, is available at https://packagist.org/packages/captcha-com/cakephp-captcha

The integration package includes a wrapper class around the regular BotDetect Captcha Library for use in your application Controllers.

The package also includes separate Controllers that handle:

  • Captcha image, sound, and resources requests, which use
    http://<MY_CAKE_WEBROOT>/captcha-handler Urls by default.

CakePHP Basic BotDetect CAPTCHA Example

This basic CakePHP 3 Captcha example shows how to use the BotDetect Captcha CakePHP composer plugin in your Controller and View code, and handling of basic Captcha user input validation.

  • Controller: <BD_CAKE_PACK>/bd-captcha-cakephp-3-examples /src/Controller/ExampleController.php
  • View: <BD_CAKE_PACK>/bd-captcha-cakephp-3-examples /src/Template/Example/index.ctp
  • Config: <BD_CAKE_PACK>/bd-captcha-cakephp-3-examples/config/captcha.php

Form Model Validation BotDetect CakePHP CAPTCHA Example

This CakePHP 3 form model validation Captcha example shows how to use BotDetect Captcha with CakePHP form and validation functionality by implementing a simple contact form.

  • Controller: <BD_CAKE_PACK>/bd-captcha-cakephp-3-examples /src/Controller/ContactController.php
  • View: <BD_CAKE_PACK>/bd-captcha-cakephp-3-examples /src/Template/Contact/index.ctp
  • Config: <BD_CAKE_PACK>/bd-captcha-cakephp-3-examples/config/captcha.php

CakePHP Auth BotDetect CAPTCHA Example

This CakePHP 3 Auth Captcha example shows how to use BotDetect Captcha with CakePHP Auth Component

  • Controller:
    • <BD_CAKE_PACK>/bd-captcha-cakephp-3-examples/src/Controller /UsersController.php
  • View:
    • <BD_CAKE_PACK>/bd-captcha-cakephp-3-examples/src/Template/Users /login.ctp
    • <BD_CAKE_PACK>/bd-captcha-cakephp-3-examples/src/Template/Users /register.ctp
  • Config:
    • <BD_CAKE_PACK>/bd-captcha-cakephp-3-examples/config/captcha.php

The provided examples are available inside of a single CakePHP app via their respective controllers:

   http://<MY_CAKE_WEBROOT>/example
   http://<MY_CAKE_WEBROOT>/contact
   http://<MY_CAKE_WEBROOT>/users/login
   http://<MY_CAKE_WEBROOT>/users/register

You can copy the whole preconfigured CakePHP app from the BotDetect Captcha CakePHP Package somewhere on your development web server and examine it there.

1. Include BotDetect CAPTCHA in Your CakePHP MVC Application

Install BotDetect CakePHP CAPTCHA composer plugin via Composer

Note: If you do not have Composer yet, you can install it by following the instructions on https://getcomposer.org

If you have Git installed on your development machine, you should use the following installation procedure:

Step 1: Install the BotDetect CakePHP Captcha Composer Plugin:

Run the following command in your application's root directory:

Step 2: Load the BotDetect CakePHP Captcha Composer Plugin in your application's bootstrap (<MY_CAKE_WEBROOT>/config/bootstrap.php):

Plugin::load('CakeCaptcha', ['routes' => true]);

A Note On PHP Session Persistence

The CakePHP CAPTCHA Plugin requires persistent per-user server storage to work properly. By default, it uses CakePHP Sessions, which is convenient in most use cases.

If your environment requires a different approach to handle Session data, you can be easily adding a custom session driver as described here.

Note that a Session cleanup right after creating a Captcha class instance may cause an error since BotDetect will not find its Session data.

2. Display BotDetect CAPTCHA In Your CakePHP View

Captcha configuration options

<?php if (!class_exists('CaptchaConfiguration')) { return; }

// BotDetect PHP Captcha configuration options

return [
  // Captcha configuration for example page
  'ExampleCaptcha' => [
    'UserInputID' => 'CaptchaCode',
    'ImageWidth' => 250,
    'ImageHeight' => 50,
  ],

];

In order to use the CakePHP CAPTCHA Plugin, you must declare Captcha configuration in config/captcha.php file following the structure given above. The ExampleCaptcha is an example name and will be used when loading the BotDetect CakePHP component in your controller. You should pick a name that best matches your usage scenario like: LoginCaptcha, ContactCaptcha, etc. You can find a full list of available Captcha configuration options and related instructions at the Captcha configuration options page.

In case you need different Captcha for another form in your application, here is the example how to add additional captcha configuration for a login form:

<?php if (!class_exists('CaptchaConfiguration')) { return; }

// BotDetect PHP Captcha configuration options

return [
  // Captcha configuration for example page
  'ExampleCaptcha' => [
    'UserInputID' => 'CaptchaCode',
    'ImageWidth' => 250,
    'ImageHeight' => 50,
  ],

  // Captcha configuration for login page
  'LoginCaptcha' => [
    'UserInputID' => 'CaptchaCode',
    'CodeLength' => CaptchaRandomization::GetRandomCodeLength(4, 6),
    'ImageStyle' => [
      ImageStyle::Radar,
      ImageStyle::Collage,
      ImageStyle::Fingerprints,
    ],
  ],

];

Load the BotDetect CAPTCHA CakePHP Component

The BotDetect CakePHP Captcha plugin uses the usual method of loading and configuring components inside of CakePHP.

<?php namespace App\Controller;
  
use App\Controller\AppController;
  
class ExampleController extends AppController
{
  public function initialize()
  {
    parent::initialize();

    // load the Captcha component and set its parameter
    $this->loadComponent('CakeCaptcha.Captcha', [
      'captchaConfig' => 'ExampleCaptcha'
    ]);
  }
}

The BotDetect MVC Captcha component is available in CakePHP code under the CakeCaptcha plugin namespace. It's loaded via loadComponent() in your Controller’s initialize() method (or you're able to load it via $components array), and then assigns it a captcha configuration key defined in config/captcha.php file. Each individual Controller action including Captcha validation should use a unique captchaConfig value to avoid persistence name clashes.

Compose Your CakePHP View With BotDetect CAPTCHA Display

Inside your View script, you should include some form elements alongside the Captcha display. In a regular form with a submit button, you need an input field where the user retypes the characters shown in the Captcha image.

You display the image by calling the captcha_image_html() helper function:

<?= $this->Form->create(null, ['action' => 'index']) ?>

<!-- show captcha image html -->
<?= captcha_image_html() ?>

<!-- Captcha code user input textbox -->
<?= $this->Form->input('CaptchaCode', [
  'label' => 'Retype the characters from the picture:',
  'maxlength' => '10',
  'style' => 'width: 270px;',
  'id' => 'CaptchaCode'
]) ?>

<?= $this->Form->button(__('Submit'), ['style' => 'float: left; margin-left: 20px;']) ?>
<?= $this->Form->end() ?>

You also need to add the BotDetect Captcha layout stylesheet by calling the captcha_layout_stylesheet_url() helper function, which CakePHP will include in the <head> of your page containing the Captcha:

<?= $this->Html->css(captcha_layout_stylesheet_url(), ['inline' => false]) ?>

BotDetect Captcha should now be visible in your App's View.

3. Validate the CAPTCHA In Your CakePHP Controller

After your Captcha is displayed alongside a form input field, you will want to validate user submitted Captcha code in a Controller action. This should always be done before any sensitive processing to confirm the submitted data is actually entered by a person and not a bot.

Validate the Submitted CAPTCHA Code User Input

The validation of Captcha code input should be performed in Controler->Action that is on the receiving end of the form submission (where the form action points to).

Usually, the submitted form data is available inside the CakePHP request object, by the same name you gave the Captcha code input field on the form where it was displayed. For example: $this->request->data['CaptchaCode'].

It is then a matter of calling the captcha_validate() helper function and passing it the user input.

// validate the user-entered Captcha code
$isHuman = captcha_validate($this->request->data['CaptchaCode']);

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

After Captcha validation, it is best to clear the previous user input automatically; since each Captcha code can only be validated once regardless of the validation result, keeping previous user input makes no sense.

Handle CAPTCHA Validation Failure / Success

You should then write some code to handle both Captcha validation success and failure. If it failed, you should abort further processing and display an error message; if it succeeded, you can proceed with the protected form action:

if ($isHuman) {
  // TODO: Captcha validation passed:
  // continue with form processing, knowing the submission was made by a human
} else {
  // TODO: Captcha validation failed:
  // abort sensitive action, return an error message
}

This will ensure that the sensitive action can not be automated and is only performed when a human fills out the form.