Captcha usando o vendor PhpCaptcha
Autor: Carlitos | Publicado: 2010-01-19T18:35:00-03:00

Bom, alguns dias sem postar nada e eu procurando algo interessante para compartilhar com vocês. Vamos lá então...

Estava quebrando a cabeça para implementar um Captcha (Isso mesmo! CAPTCHA, ou seja, aquelas letrinhas todas bagunçadas que impedem que um "não-humano" consiga submeter um formulário automaticamente... se bem que as vezes até um humano não consegue identificar as letras, mas vamos lá).

Baseado neste artigo que vi no Bakery vamos utilizar o PhpCaptcha como vendor. Segue os passos:

1) Faça o download do PhpCaptcha através do link http://www.ejeliot.com/pages/2 e descompacte o arquivo em "app/vendors/phpcaptcha" (crie este diretório caso não exista).

2) Faça o download dos arquivos de fontes Vera do GNOME através do link http://ftp.gnome.org/pub/GNOME/sources/ttf-bitstream-vera/1.10/ttf-bitstream-vera-1.10.zip e descompacte o arquivo em  "app/vendors/phpcaptcha/fonts/".

3) Vamos criar o componente Captcha:
&lt;?php

// Salve em app/controllers/componentes/captcha.php

App::import('Vendor','PhpCaptcha' ,array('file'=>'phpcaptcha'.DS.'php-captcha.inc.php'));

class CaptchaComponent extends Object
{
  var $controller;

  function startup( &amp;$controller ) {
    $this->controller = &amp;$controller;
  }

  function image(){

    $imagesPath = APP . 'vendors' . DS . 'phpcaptcha'.'/fonts/';

    $aFonts = array(
      $imagesPath.'VeraBd.ttf',
      $imagesPath.'VeraIt.ttf',
      $imagesPath.'Vera.ttf'
    );

    $oVisualCaptcha = new PhpCaptcha($aFonts, 200, 60);

    $oVisualCaptcha->UseColour(true);
    //$oVisualCaptcha->SetOwnerText('Source: '.FULL_BASE_URL);
    //$oVisualCaptcha->SetNumChars(6);
    $oVisualCaptcha->Create();
  }

  function audio(){
    $oAudioCaptcha = new AudioPhpCaptcha('/usr/bin/flite', '/tmp/');
    $oAudioCaptcha->Create();
  }

  function check($userCode, $caseInsensitive = true){
    if ($caseInsensitive) {
      $userCode = strtoupper($userCode);
    }

    if (!empty($_SESSION[CAPTCHA_SESSION_ID]) &amp;&amp; $userCode == $_SESSION[CAPTCHA_SESSION_ID]) {
      // clear to prevent re-use
      unset($_SESSION[CAPTCHA_SESSION_ID]);

      return true;
    }
    else
      return false;
  }
}
?&gt;

4) Adicione os métodos aos controllers que desejar. No caso vou adicionar ao controller Users:
&lt;?php
class UsersController extends AppController
{
  ...
  // Adicione o componente Captcha ao controller
  var $components = array('Captcha');
  ...
  function captcha_image(){
    Configure::write('debug',0);
    $this->layout = null;
    $this->Captcha->image();
    $this->render();
  }

  // Não vou entrar no mérito do captcha com audio
  function captcha_audio()
  {
    $this->Captcha->audio();
  }
  ...
}
?&gt;

5) Na view invoque o método captcha_image:
&lt;img id="captcha" src="&lt;?php echo $html->url('/users/captcha_image'); ?&gt;" alt="" /&gt;

6) Agora para verificar se o usuário digitou corretamente os caracteres do Captcha usamos a função check, veja:
// Suponha que o campo texto onde o usuário preencheu os caracteres que leu
// no captcha seja "captcha", então temos
if(!$this->Captcha->check($this->data['User']['captcha'])){
  $this->Session->setFlash('Você não preencheu corretamente as letras da imagem!');
}


Veja como fica o resultado deste captcha colorido:


Bom, espero que funcione, pois aqui funcionou. Tem outros captchas para Cake e PHP também, veja aqui.

Abração!