Co to jest CAPTCHA, każdy wie. No, moze nie każdy jest świadomy, że przepisując tekst z obrazka rozwiązuje test (Completely Automated Public Turing test to tell Computers and Humans Apart) który ma za zadanie odróżnić człowieka od maszyny i zapobiec wypełnianiu naszych formularzy przez roboty.
Z tym, że ten artykuł nie jest dla tych którzy żyją nieświadomi co i w jakim celu wypełniają. :)
Jako programista aplikacji internetowych średnio co kilka dni wstawiam gdzieś captchę. Dobrze jest sobie to ułatwiać, dlatego stworzyłem komponent do Zend Framework-a. Mam nadzieję, że komuś się przyda.
Jak każdej standardowej captch-y w Zend Framwork-u :)
// Tworzymy instancję Zend_View $view = new Zend_View(); // W pierwszym widoku: $captcha = new Zend_Captcha_Captchator(); $id = $captcha->generate(); echo ""; // W kolejnym rządaniu: // Założmy, ze ustawiona w poprzednium rządaniu wartość $_POST['foo'] // będziwe stanowiła wartość captch-y input => captcha value if ($captcha->isValid($_POST['foo'], $_POST)) { // Sukces, captcha prawidłowa! }
Można nawet pominąć metodę generate()
Dodatkowo jeśli ktoś chce do formularza wyciągnąć jedynie adres obrazka to ma do dyspozycji metodę getImgUrl()
Jak to działa można zobaczyć na demonstracji http://smoku.net/artykuly/zend-captcha-captchator-demo
/** Zend_Captcha_Base */
require_once 'Zend/Captcha/Base.php';
class Example_Captcha_Captchator extends Zend_Captcha_Base
{
/**#@+
* Error codes
* @const string
*/
const MISSING_VALUE = "missingValue";
const ERR_CAPTCHA = "errCaptcha";
const BAD_CAPTCHA = "badCaptcha";
/**#@-*/
/**
* Error messages
* @var array
*/
protected $_messageTemplates = array(
self::MISSING_VALUE => "Empty captcha value",
self::ERR_CAPTCHA => "Captcha error",
self::BAD_CAPTCHA => "Captcha value is wrong",
);
protected $_imgWidth = 130;
protected $_imgHeight = 90;
protected $_imgAlt = "Captcha Image";
protected $_imgUriTpl = "http://captchator.com/captcha/image/%1s";
protected $_validateUriTpl = "http://captchator.com/captcha/check_answer/%s/%s";
protected $_personId;
/**
* Constructor
*
* @param null|string|array|Zend_Config $options
* @param null|string $personId
* @return void
*/
public function __construct($options = null, $personId = null)
{
parent::__construct($options);
$this->setPersonId($personId);
}
/**
* Generate a new captcha
*
* @return string new captcha ID
*/
public function generate(){
$personID = $this->getPersonId();
if(empty($personID)){
$this->setPersonId();
}
}
/**
* Display the captcha
*
* @param Zend_View_Interface $view
* @param mixed $element
* @return string
*/
public function render(Zend_View_Interface $view = null, $element = null)
{
$html = "<"."img";
$html .= " width=\"".$this->getImgWidth()."\"";
$html .= " height=\"".$this->getImgHeight()."\"";
$html .= " alt=\"".$this->getImgAlt()."\"";
$html .= " src=\"".$this->getImgUrl()."\"";
$html .= " />";
$html .= "<"."br"." />";
return $html;
}
/**
* Validate captcha
*
* @see Zend_Validate_Interface::isValid()
* @param mixed $value
* @return boolean
*/
public function isValid($value)
{
$value = preg_replace( "/[^a-z0-9]+/i", "", strval($value) );
if (empty($value)) {
$this->_error(self::MISSING_VALUE);
return false;
}
$service = new Zend_Http_Client( $this->_getValidateUrl( $value ) );
if (!$service) {
$this->_error(self::ERR_CAPTCHA);
return false;
}
$res = $service->request(Zend_Http_Client::GET);
if (!$res) {
$this->_error(self::ERR_CAPTCHA);
return false;
}
if (!$res->isSuccessful()) {
$this->_error(self::ERR_CAPTCHA);
return false;
}
if( trim($res->getBody()) == "0" ){
$this->_error(self::BAD_CAPTCHA);
return false;
}elseif( trim($res->getBody()) != "1" ){
$this->_error(self::ERR_CAPTCHA);
return false;
}
return true;
}
private function getImgUrl()
{
$this->generate();
return sprintf( $this->_getImgUriTpl() , $this->getPersonId() );
}
private function setPersonId($personId = null)
{
if(is_string($personId)){
$personId = preg_replace( "/[^a-z0-9]+/i", "", $personId );
if(!empty($personId)){
$this->_personId = $personId;
return true;
}
}
if(Zend_Session::isStarted()){
//$this->_personId = preg_replace( "/[^a-z0-9]+/i", "", Zend_Session::getOptions("name") ).substr( Zend_Session::getId() , 0 , 15 );
$this->_personId = substr( Zend_Session::getId() , 0 , 15 );
return true;
}else{
$this->_error(self::ERR_CAPTCHA);
return false;
}
}
private function getPersonId(){
return strval($this->_personId);
}
public function setImgUriTpl($uri)
{
if(strval($uri) && !empty($uri)){
$this->_imgUriTpl = strval($uri);
}
}
public function setValidateUriTpl($uri)
{
if(strval($uri) && !empty($uri)){
$this->_imgValidateUriTpl = strval($uri);
}
}
public function setImgWidth($width)
{
if(intval($width)){
$this->_imgWidth = intval($width);
}
}
public function getImgWidth()
{
return intval($this->_imgWidth);
}
public function setImgHeight($height)
{
if(intval($height)){
$this->_imgHeight = intval($height);
}
}
public function getImgHeight()
{
return intval($this->_imgHeight);
}
public function setImgAlt($imgAlt)
{
if(is_string($imgAlt) && !empty($imgAlt)){
$this->_imgAlt = $imgAlt;
}
}
public function getImgAlt()
{
return strval($this->_imgAlt);
}
protected function _getImgUriTpl()
{
return strval($this->_imgUriTpl);
}
protected function _getValidateUriTpl()
{
return strval($this->_validateUriTpl);
}
protected function _getValidateUrl($value)
{
$this->generate();
return sprintf( $this->_getValidateUriTpl() , $this->getPersonId() , $value );
}
}