Tuesday, 19 August 2014
How to Add BotDetect PHP CAPTCHA Protection to CakePHP Applications
The BotDetect CAPTCHA CakePHP Download Package
Because CakePHP is a MVC framework that leverages certain conventions to provide a rich set of functionality to PHP application developers, implementing BotDetect Captcha requires a layer of integration code to conform to those conventions. This enables BotDetect Captcha to integrate seamlessly into CakePHP applications and be used according to expectations of CakePHP developers.
Path Aliases Used Throughout This Guide
<MYCAKEAPP>
: your CakePHP app directory (same as theAPP_DIR PHP
CakePHP constant)<BDCAKEPACK>
: the downloaded and extracted contents of the BotDetect Captcha CakePHP Package<BDLIB>
: the downloaded and extracted contents of the BotDetect PHP Captcha library
For convenience purposes we are providing the BotDetect Captcha CakePHP integration code packaged as a CakePHP plugin.
You can get the whole BotDetect Captcha CakePHP integration package here. Included in this package is the integration code, a basic Captcha validation sample, and a sample showing use of BotDetect Captcha with CakePHP
FormHelper
and model validation.
(The BotDetect Captcha PHP Library is a required and separate download availablehere.)
The BotDetect CAPTCHA CakePHP Plugin
BotDetect CakePHP Plugin code, sans the Captcha library, is located at
<BDCAKEPACK>/app/Plugin/Botdetect
.
The code includes a Captcha component for use in your application Controllers, and a separate Controller that handles Captcha image and sound requests. This Captcha Controller uses
http://<MYCAKEAPP>/botdetect/captcha
Urls by default.CakePHP Basic BotDetect CAPTCHA Sample
This basic CakePHP Captcha sample shows how to use the BotDetect Captcha CakePHP plugin in your Controller and View code, and handling of basic Captcha user input validation.
- Controller:
<BDCAKEPACK>/app/Controller/SampleController.php
- View:
<BDCAKEPACK>/app/View/Sample/index.ctp
CakePHP Form Model Validation BotDetect CAPTCHA Sample
This CakePHP form model validation Captcha sample shows how to use BotDetect Captcha with CakePHP form and validation functionality by implementing a simple contact form.
- Controller:
<BDCAKEPACK>/app/Controller/ContactController.php
- Model:
<BDCAKEPACK>/app/Model/Contact.php
- View:
<BDCAKEPACK>/app/View/Contact/index.ctp
The provided samples are available inside of a single CakePHP app via their respective controllers (
http://<MYCAKEAPP>/sample
and http://<MYCAKEAPP>/contact
). 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
Copy the Necessary BotDetect CAPTCHA Files
The base BotDetect Captcha library and CakePHP MVC Captcha integration code are distributed separately and need to be merged so you can use them in your CakePHP app.
1. BotDetect CakePHP CAPTCHA Plugin
Copy (the whole directory and all contents)<BDCAKEPACK>/app/Plugin/Botdetectto
<MYCAKEAPP>/Plugin/Botdetect
2. BotDetect CAPTCHA Library Code
Copy (the whole directory and all contents)<BDLIB>/libto
<MYCAKEAPP>/Plugin/Botdetect/lib
3. Public BotDetect Resources
Copy (the whole directory and all contents)<BDLIB>/lib/botdetect/publicto
<MYCAKEAPP>/webroot/botdetect/public
Public Captcha resources (icon images, JavaScript and Css files) need to be available via Url. It is possible to use a different location for them than the one shown above, but then you have to also adjust the
<MYCAKEAPP>/Plugin/Botdetect/lib/botdetect/CaptchaConfig.php
fileCaptcha Url settings.Load the BotDetect CAPTCHA Plugin in Your CakePHP Application
Your CakePHP app needs to be made aware of the BotDetect Captcha plugin. This is done inside your application's bootstrap (
You can use either<MYCAKEAPP>/Config/bootstrap.php
).CakePlugin::loadAll();or
CakePlugin::load('Botdetect');
at the end of your
bootstrap.php
file.
Please note that the whole MVC Captcha library is not loaded at every request; this is just letting the CakePHP application know about the plugin and leverages Cake's lazy-loading infrastructure to load the BotDetect code when it's actually needed.
That's it. BotDetect Captcha is ready to be used in your CakePHP application.
A Note On PHP Session Persistence
The BotDetect Captcha Library requires persistent per-user server storage to work properly. By default, it uses standard PHP Sessions, which is convenient in most use cases.
If your environment requires a different approach to handling Session data, you can implement your own Captcha persistence methods via the provided BotDetect Captcha persistence hooks in the
lib/botdetect/CaptchaConfig.php
file.
Also, the BotDetect Captcha CakePHP integration code has a single direct call to
session_start()
to make sure the Session is available for the component at the time of loading. This call is located in the startup method for the component, in<MYCAKEAPP>/Plugin/Botdetect/Controller/Component/CaptchaComponent.php
, lines 9-11.
If your CakePHP application is handling Sessions in a non-standard way (i.e. there is no PHP
$_SESSION
global available), you may need to remove this call, as well as implementing the config file changes mentioned above.2. Display BotDetect CAPTCHA In Your CakePHP View
Before displaying the Captcha in your View, the related Controller needs to load the BotDetect component and set a proper name for your Captcha instance. It also needs to pass the Captcha markup to the View, which can then display it alongside other form elements.
Load the BotDetect CAPTCHA CakePHP Component
The BotDetect CakePHP Captcha plugin uses the usual method of loading and configuring components inside of CakePHP.
class SampleController extends AppController { // Your controller var $components = array( 'Botdetect.Captcha' => array( 'CaptchaId' => 'SampleCaptcha', // a unique Id for the Captcha instance 'UserInputId' => 'CaptchaCode' // Id of the Captcha code input textbox ) );
The BotDetect MVC Captcha component is available in CakePHP code under the
Botdetect
plugin namespace. It's loaded to the $components
array in your Controller, and is supplied a unique name through the CaptchaId
component setting. Each individual Controller action including Captcha validation should use a unique CaptchaId
value to avoid persistence name clashes.
The additional
UserInputId
setting is used to setup client-side functionality operating on the Captcha code input field.Pass the BotDetect CAPTCHA HTML Markup to the CakePHP View
The CakePHP MVC Captcha component generates its own markup, which should be made available to your View. The Captcha Html is retrieved by calling the
Html()
method on theCaptcha
component object. It is then made available to the view by setting a variable withController::set()
.class SampleController extends AppController { // Your controller var $components = array( 'Botdetect.Captcha' => array( 'CaptchaId' => 'SampleCaptcha', // a unique Id for the Captcha instance 'UserInputId' => 'CaptchaCode' // Id of the Captcha code input textbox ) ); public function index(){ // your controller action $this->set('captchaHtml', $this->Captcha->Html()); } }
The Captcha markup is now available inside your View's
$captchaHtml
variable.Compose Your CakePHP View With BotDetect CAPTCHA Display
Inside your View's
.ctp
script, you should include some form elements alongside the Captcha display. You can use either straight markup or the CakePHP FormHelper
. 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 outputting the
$captchaHtml
variable from the previous step:echo $this->Form->create(false, array('action' => 'index')); echo $captchaHtml; echo $this->Form->input('CaptchaCode'); echo $this->Form->submit(); echo $this->Form->end();
You also need to add the BotDetect Captcha layout stylesheet, which CakePHP will include in the
<head>
of your page containing the Captcha:$this->Html->css(array('/botdetect/public/lbd_layout'), 'stylesheet', array('inline' => false));
The Captcha should now be visible and functioning in your View.
3. Validate the CAPTCHA In Your CakePHP Controller
After your Captcha is displayed alongside a form input field, you will want to validate the user submitted Captcha code in the 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 done in the 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
Validate()
method of the Captcha component object and passing it the user input.// assuming "CaptchaCode" input field id $isHuman = $this->Captcha->Validate($this->request->data['CaptchaCode']); 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.
Setting id of input wrapper div in cakephp and hiding…
It might be a simple thing for most of CakePHP pro’s but at the same time it could be a tricky thing for CakePHP newbies. I just caught one newbie CakePHP developer of my team spending time on figuring this out thus adding it here for future reference. I hope it helps someone else as well.
So this about setting a ID of the wrapper div which contains label and input field in a CakePHP form. Consider the following example:
echo $this->Form->input(‘username’);
which outputs:
<div class=”input text”>
<label for=”BookPrice”>Price</label>
<input name=”data[Book][Price]” maxlength=”150″ type=”text” id=”BookPrice”>
</div>
<label for=”BookPrice”>Price</label>
<input name=”data[Book][Price]” maxlength=”150″ type=”text” id=”BookPrice”>
</div>
Imagine that in a case you wanted to hide this entire div and wanted to show some click event and for this to happen you want a ID attached to this div element. By the virtue of CakePHP it is quite simple provided you have read related documentation. To add an ID to hide it by default you obviously would want to add id=”price-wrapper” and style=”display:none” to the <div> element with classes “input text”. Just revisit the line above and write it as:
echo $this->Form->input(‘username’, array(‘div’=>array(‘id’ => ‘price-wrapper’, ‘style’=>’display:none;’)));
and it will output:
<div class=”input text” id=”price-wrapper” style=”display:none;”>
<label for=”BookPrice”>Price</label>
<input name=”data[Book][Price]” maxlength=”150″ type=”text” id=”BookPrice”>
</div>
<label for=”BookPrice”>Price</label>
<input name=”data[Book][Price]” maxlength=”150″ type=”text” id=”BookPrice”>
</div>
which you wanted. Isn’t that simple!
Installing PHPUnit in wamp in Windows7
Installing PEAR package manager
Add php directory to your
Windows’ Environment Variables PATH, if it is not already added. My wamp php
path is “C:\wamp\bin\php\php5.3.13″. Check Adding to Environment Variables Path if
you are not sure how to add a value to Environment Variables Path in Windows 7.
Download
http://pear.php.net/go-pear.phar to some location in your system. I downloaded
it to C:\wamp\bin\php\php5.3.13
Open a new command prompt as
an administrator and cd to the directory where go-pear.phar is placed.
I did:
cd
c:\wamp\bin\php\php5.3.13
and run
php go-pear.phar
It will ask you for
install as option for which i chose “local” which is recommended. Follow the
rest of process and it should install pear in a matter of few seconds.
Installing PHPUnit
Open a new command prompt as
an administrator and run:
pear
config-set auto_discover 1
pear
install pear.phpunit.de/PHPUnit
Specify your in
use php.ini file so the PHPUnit could make changes to it. Follow the
rest of process normally and it will install the PHPUnit.
Running test case in command prompt
Create a php file test.php
with the following code and place it at server root i.e. C:\wamp\www or
similar:
<?php
class MyTest extends
PHPUnit_Framework_TestCase
{
public function
testOneEqualsOne()
{
$this->assertEquals(1,
1);
}
}
?>
Now open the command
prompt as an administrator and run:
$ cd c:/wamp/www
$ phpunit test.php
It should output the test
results as:
PHPUnit 3.6.11 by
Sebastian Bergmann.
.
Time: 1 second,
Memory: 3.50Mb
OK (1 test, 1
assertion)
Running test case in CakePHP
NOTE: This is tricky.. This
comes into play when you try to run tests through your web browser, for example
running CakePHP unit tests. As the wamp installer had created two copies of
php.ini file, one placed at C:\wamp\bin\apache\apache2.2.22\bin and another at
C:\wamp\bin\php\php5.3.13\. In my case, the pear installer detected php.ini
file placed at the later location and made changes to it. I guess it might have
asked me to choose php.ini file while installing but i ignored it and it chose
the file it suggested and thus the following changes to add pear to include_path were
made to C:\wamp\bin\php\php5.3.13\php.ini file.
;***** Added by go-pear
include_path=".;C:\wamp\bin\php\php5.3.13\pear"
;*****
include_path=".;C:\wamp\bin\php\php5.3.13\pear"
;*****
Make sure that you had
chosen the right file. Double check the ini.php file used by wampserver. If the
instaler didn’t make changes to php.ini file used by wampserver you need to
copy these changes. Just copy these three lines of code to
C:\wamp\bin\apache\apache2.2.22\bin\php.ini file and restart the wamp server.
Visit an url of CakePHP
application while debug mode set to greater than 0. For example:
http://mysite.localhost/test.php
And it should show the
test results.
Subscribe to:
Posts (Atom)