Integrate CakePHP with Kcaptcha
Simple way to integrate CakePHP with Kcaptcha.
KCAPTCHA is a free and open source PHP solution to generate human validation images (CAPTCHA).
KCAPTCHA is meant to be a very strong protected one but requires no special hosting featires, only PHP with GD library.
You can download Kcaptcha from here: http://captcha.ru/en/kcaptcha/. After this, put kcaptcha folder into vendors directory.
Create Captcha component:
Component Class:
<?php
class CaptchaComponent extends Object
{
function startup(&$controller)
{
$this->controller = $controller;
}
function render()
{
vendor('kcaptcha/kcaptcha');
$kcaptcha = new KCAPTCHA();
$this->controller->Session->write('captcha', $kcaptcha->getKeyString());
}
}
?>
Use this component in UsersController:
Controller Class:
<?php
class UsersController extends AppController
{
...
var $components = array('Session', 'Captcha');
...
function captcha()
{
$this->Captcha->render();
}
...
}
?>
Create image tag in view:
View Template:
<img src="<?php echo $html->url('/users/captcha'); ?>" />
That's all :)








After spending lot of time on it, i was able to figure out that there was a newline at the end of one of the model file. After removing that newline, the image started showing.
Hence remove all the extra spaces at the end of model files used by the controller.
Do something along the lines of this, in the user controller:
function beforeFilter() {parent::beforeFilter();
$this->Auth->allow('some_action', 'forgotpass', 'resetpass' , 'captcha');
}
App::import('Vendor', 'kcaptcha/kcaptcha');
instead of:
vendor('kcaptcha/kcaptcha');
Ideally, the kcaptcha code should already do this, but since it doesn't (and I don't like modifying vendor code)...
Just add this to your controller action:
$this->disableCache();
I tried KCAPTCHA and I had the same problems as described on post (11). And I did found an answer to this question : "how can i get Cake to output the image correctly ?"
Well, rather than putting the render() method in a component, I created this controller :
Controller Class:
<?php
class CaptchaController extends AppController {
var $name = 'Captcha';
var $uses = array();
function index(){
vendor('kcaptcha'.DS.'kcaptcha');
$kcaptcha = new KCAPTCHA();
$this->Session->write('captcha', $kcaptcha->getKeyString());
}
}
?>
In my login view i have put :
View Template:
The javascript beneath the captcha answers the question of the post (16). "how it is possible to change the captcha image with an ajax request?". Well there's no need for an ajax request to update the captcha....
<?php
echo $form->labelTag('Captcha/usercode', 'Are you human ?').'<br/>';
echo '<img id="captcha" src="'.$html->url('/captcha').'" alt="Captcha" ></img><br/>';
echo $html->input('Captcha/captcha').'<br/>';
echo '<a href="javascript:void(0);" onclick="javascript:document.images.captcha.src=\''.$html->url('/captcha').'\'">Reload?</a><br/>';
?>
...
In the captcha component I have put :
Component Class:
<?php
And finally I can put in the login action :class CaptchaComponent extends Object
{
function startup(&$controller){
$this->controller = $controller;
}
function validateCaptcha($fieldName, $params = array()) {
$name = $this->controller->name;
if(isset($params['name'])){
$name = $params['name'];
}
$val = $this->controller->data[$name][$fieldName];
if (!defined('captcha'))
define('captcha', 'kcaptcha');
if (!empty ($_SESSION['captcha']) && $val == $_SESSION['captcha']) {
// clear to prevent re-use
unset ($_SESSION['captcha']);
return true;
}
return false;
}
}
?>
if($this->Captcha->validateCaptcha('captcha',array('name'=>'Captcha'))){
}
It worked for me, I hope that It'll work for you. I'm using kcaptcha 1.2.5 and cake 1.18.
how it is possible to change the captcha image with an ajax request?
thank u very much for your help.
Regards,
Maidi
First you need to check you have GD, doing a
<?php echo phpinfo(); ?>will tell you if you have that.Once I had it working I add a function to validation.php file (like Spout did in http://bakery.cakephp.org/articles/view/captcha-component-with-phpcaptcha) but with some changes
in captcha() function I add this (not really necessary)<?php
function validateCaptcha($fieldName, $params) {
$val = $this->data[$this->name][$fieldName];
if(!defined('captcha'))
define('captcha', 'kcaptcha');
if (!empty($_SESSION['captcha']) && $val == $_SESSION['captcha']) {
// clear to prevent re-use
unset($_SESSION['captcha']);
return true;
}
return false;
}
?>
My view looks like thisfunction captcha(){
if ($this->referer() != "/users/registro"){ /* "/users/registro" is the view I am calling captcha() from */
$this->redirect("/");
}
else {
$this->Captcha->render();
}
}
You might wonder what is that hidden field for, someone said (don't remember where, sorry) that idea and I added, sometimes bots fills all fields they find, so we leave this field empty, if the controller checks the field is not empty then we are dealing with a bot.<?php echo $html->hidden("User/foo")?>
<p>Enter the text that appears above</p>
<p>
<?php echo $html->input('User/captchaText');?>
<?php echo $error->fieldErrors('User/captchaText'); ?>
</p>
Finally, in my controller I added this validation rule (so you can see how to do it on your model) as well the hidden field conditional
if (empty($this->data['User']['foo'])) {
$this->User->validate = array('captchaText' => array('Mycaptcha' => array('method' => 'validateCaptcha', 'message' => 'your error message')));
...
}
This echo is used to output performance info but it is corrupting the image file.
the situation:
my image tag in the view:
and a textarea for a message:
$html->textarea('Invitation/personal', array('cols'=>'42', 'rows'=>'4')); ?>
i have a submit button that must generate a new captcha image and the data in the textarea must remain preserved / saved.
echo $html->submit('new ID'); ?>
but my problem is that i dont know how to implement this in cakephp. When i press the submit button (new ID) that the image is a new captcha image and the entered data in the textarea is saved!?
the form:
can you help me? thanks!
PS: sorry for my bad english :(
MfG Maidi
After 2 nights of suffering and 12 search tabs open in Firefox, i reached the following conclusions:
- KeyString generation works fine and the keystring gets stored in Session.
- The image is generated but the headers are always sent wrong. Even if $layout = "" .. or $layout = null etc.. and even if you exit() after calling $this->Captcha->render().
- Never use IE for debugging .. use Firefox's document source.
I revised my code thoroughly for hidden spaces and missing functions .. everything is clean and still no results.
- Cakephp is not for people with high blood pressure.
- A standalone KCAPTCHA works perfectly. Therefore, all what you need is to use the index.php (that is packeged with KCAPTCHA) directly as the src of your img tag .. and to hell with Cakephp's "Vendor" crap.
now .. my question is .. how can i get Cake to output the image correctly ?
Thanks in advance.
P.S. source code will be available upon request
With CakePHP it is really rapid development!
This line have an error:
$this->controller->Session->write('captcha', $kaptcha->getKeyString());
Must be:
$this->controller->Session->write('captcha', $kcaptcha->getKeyString());
Missing 'c' y kcaptcha object ;-)
Everything is corect but no image :(
help me please
But in debug mode 1 - I don't see error.
Error in Kcaptcha?
When I look url: site.com/users/captcha - I see JFIF bla bla may be valid code?) but at the end - I see layout. May be problem here?
Check the kcaptcha docs, see what they require and then check with your host to see if they provide it.
later
So. After some fun with placing $this->layout = '';
I get this:
http://surnin.kiev.ua/users/captcha (you see - this image, but wrong header).
So image generating, but not showing - wrong header... Why?
COnstruction
img src=" echo html-> ...." -not work.
Sorry for bad english ;)
In your response headers, the image is served as Content-Type: text/html
But why here this header? ;-)
I do all by this manual... Even creating empty captcha.thtml (without this file - not work).
Till this time I cann't find - where put wrong header.
When I past/copy code from this page, I copy also " " in component & controller code... Then I get wrong header.
After removing "?> " in both files I got result.
Sorry for all & thanks! ;-)
Admittedly, I'm new to cakePHP.
I really need to implement a captcha system into the guestbook on my website.
I'm having difficulty integrating the files for kcaptcha into my cake structure.
Firstly, there are 2 vendors directories:
1. /cake/vendors/
2. /cake/app/vendors/
Which vendors directory am I supossed to have the kcaptcha folder located in?
Secondly, I'm having difficulty working out exactly where the above snippets of code are meant to go. Not providing an exact filename and/or directory location for the file is not helpful, especially to those of us who understand the fundementals of cakePHP but are still to master it's exact goings on and folder structure.
So, for the first code snippet ("Create Captcha component:") I created the following file containing the code: /cake/app/controllers/components/captcha_component.php. Is this correct? If not, what should the file be named and where should it be located?
For the second code snippet ("Use this component in UsersController:") to be honest I had no idea what to do with this. What confuses me is that it refers to UsersController which suggests to me that the code snippet needs to be incorporated into an existing controller named users_controller.php. If this is the case where is this controller because I couldn't locate it anywhere in my cake directories?
For the third code snippet ("Create image tag in view:") I'm added the code to an existing view file where I want the captcha to appear. Is this correct? Do I need to create any view files specifically for the kcaptcha???
I'd really appreciate some help. I'm sure it's quite simply to install and get going but please don't put new cakePHP users off using cakePHP and vendors by assuming that anyone using it is already an expert. We all needed to start somewhere afterall and to become an expert at anything you first need to be a novice!
Thank you.
Comments are closed for articles over a year old