Image Auth – CAPTCHA component March 16, 2006
Posted by rossoft in CakePHP.trackback
A human verification system through a text image
1. Include the component.
var $components =array (‘xxx’,'yy’,'imageAuth’);
2. In the login action:
$this->imageAuth->generate();
3.
Create a new action for showing the image: /login/image_auth
function image_auth()
{
$this->imageAuth->show();
}
4.
In the login form:<img src=”<?=$html->url(’/login/image_auth’)?>” />
5. Put this in vendors/image_auth/
6. In your post-action:
if (! $this->imageAuth->check( $this->params['data']['text'] ))
{
echo ‘Wrong text entered’;
}
7. Put this code in controllers/components/image_auth.php
<?php
/*
* Image Auth component.
* Real human verification system for forms
*
* @author RosSoft
* @version 0.1
* @license MIT
*
* @link http://phpbuilder.com/columns/patterson20060301.php3
*/
class ImageAuthComponent extends Object
{
var $components = array(‘session’);
var $controller;
/** Font file */
var $font=’ProggyCleanSZBP’;
/** some background colors */
var $bg_colors = array(
’176.196.222′, // Blue
’204.153.204′, // Purple
’204.204.204′, // Gray
’227.81.82′, // Red
’150.200.162′ // Green
);
/** Some font colors */
var $font_colors = array(
’0.0.139′, // Blue
’104.34.139′, // Purple
’79.79.79′, // Gray
’128.0.0′, // Red
’59.94.15′ // Green
);
/** Image width */
var $img_width = 170;
/** Image height */
var $img_height = 75;
/** Font size */
var $fnt_size = 24;
/** Letter spacing */
var $let_space = 10;
/** Length of random string */
var $str_length = 6;
function startup(&$controller)
{
$this->controller=$controller;
}
/**
* Generates a new random string and stores on session
* @param boolean $regenerate. If false and already exists a random string then it’s reused
*/
function generate($regenerate=true)
{
if (! $regenerate)
{
$regenerate= ! $this->session->check(‘image_auth_string’);
}
if ($regenerate)
{
$rnd_str = $this->_gen_random_string($this->str_length);
$this->session->write(‘image_auth_string’,$rnd_str);
}
}
/**
* Outputs the random string as an image.
* The string is readed from the session
*/
function show()
{
$this->generate(false); //Generates a new string if there isn’t a generated one
$rnd_str=$this->session->read(‘image_auth_string’);
// Set GD font path
putenv(‘GDFONTPATH=’.realpath(VENDORS . ‘image_auth’));
/**
* Image functions
*/
// Create the image
$img = imagecreate($this->img_width, $this->img_height) or die(‘Can not initialize GD Image Library’);
// Define Background & Text colors
list($br, $bg, $bb) = explode(‘.’, $this->bg_colors[rand(0, count($this->bg_colors)-1)]);
list($tr, $tg, $tb) = explode(‘.’, $this->font_colors[rand(0, count($this->font_colors)-1)]);
$bg_color = imagecolorallocate($img, $br, $bg, $bb);
$txt_color = imagecolorallocate($img, $tr, $tg, $tb);
$line_clr = imagecolorallocate($img, 0, 0, 0);
// Create box around image
imageline($img, 0, 0, $this->img_width, 0, $line_clr); // Top left to top right
imageline($img, 0, 0, 0, $this->img_height, $line_clr); // Top left to bottom left
imageline($img, 0, $this->img_height-1, $this->img_width, $this->img_height -1, $line_clr); // Bottom Left to Bottom right
imageline($img, $this->img_width-1, 0, $this->img_width-1, $this->img_height, $line_clr); // Top right to bottom Right
// Write string into image
for($i=0; $i
{
imagettftext($img, (rand() % $this->fnt_size / 1.5) + $this->fnt_size, rand(-30, 30), (($i*$this->fnt_size)+$this->let_space), rand($this->fnt_size+5, ($this->img_height – $this->fnt_size-5)), $txt_color, $this->font, $rnd_str{$i});
}
imagefilter($img,IMG_FILTER_GAUSSIAN_BLUR,200);
header(“Pragma: public”);
header(“Expires: 0″);
header(“Cache-Control: no-store, no-cache”);
header(“Cache-Control: must-revalidate, post-check=0, pre-check=0″);
header(“Cache-Control: public”);
if (function_exists(‘imagepng’))
{
header(“Content-type: image/png”);
imagepng($img);
}
else
{
header(“Content-type: image/jpeg”);
imagejpeg($img);
}
$this->controller->autoRender=false;
}
/**
* Checks the string passed against session for a valid auth
* @param string $string String to be checked
* @return boolean. True if valid
*/
function check($string)
{
return ($string === $this->session->read(‘image_auth_string’));
}
/**
* Random string generation function
*/
function _gen_random_string($length=5, $str=”)
{
for($i=1; $i<=$length; $i++)
{
$ord = rand(48, 90);
if( ( ($ord>=48) && ($ord<=57) ) || ( ($ord>=65) && ($ord<=90) ) )
{
$str .= chr($ord);
}
else
{
$str .= $this->_gen_random_string(1);
}
}
return $str;
}
}
You have a typo:
if (function_exists(’imagegng’))
Should be:
if (function_exists(’imagepng’))
Beside that, it’s quite an awsome feature !!
Thanks !!
thanks, i’ve corrected the code
Hi RosSoft,
while I appreciate your work on this I think it shouldn’t be used. The reason is that captchas are more effective with blocking blind people then they are for bots.
Bots (can) use two technics for spaming a captcha protected site:
- They can use some graphic recognition to read it -> check out http://sam.zoy.org/pwntcha/ if you don’t believe it.
- They present one of your captcha’s to a human user on some fake website (most likely xxx) and will use humans to easily solve tons of captchas
So what else should be used? While there is no ultimate weapon against spam bots the following techniques are fairly good:
- Create some input fields that should stay empty and hide them with css -> only bot’s will fill them out automatically. (Name them ‘email’ to make them appear extra juicy to the bot.
- Use unique form id’s for every request. Most most bots won’t reload your page for every attack and will cache your form fields the first time
- Use simple filters to block post’s containing links and the word viagra … ; )
cheers, Felix Geisendörfer, aka the_undefined
Near
// Write string into image
Should be
for($i=0; $i
Near
// Write string into image
Should be
for($i=0; $i<strlen($rnd_str); $i++)
Also
imagefilter($img,IMG_FILTER_GAUSSIAN_BLUR,200);
Is available for PHP 5 only
Thanks for the good component.
thanks, after editing some mistakes anothers appear… the tags are deleted.
imagefilter is optional, isn’t necessary
Warning: imagettftext() [function.imagettftext]: Could not find/open font in /home/lovers/ftp/app/controllers/components/image_auth.php on line 107
Warning: imagettftext() [function.imagettftext]: Could not find/open font in /home/lovers/ftp/app/controllers/components/image_auth.php on line 107
Warning: imagettftext() [function.imagettftext]: Could not find/open font in /home/lovers/ftp/app/controllers/components/image_auth.php on line 107
Warning: imagettftext() [function.imagettftext]: Could not find/open font in /home/lovers/ftp/app/controllers/components/image_auth.php on line 107
Warning: imagettftext() [function.imagettftext]: Could not find/open font in /home/lovers/ftp/app/controllers/components/image_auth.php on line 107
Warning: imagettftext() [function.imagettftext]: Could not find/open font in /home/lovers/ftp/app/controllers/components/image_auth.php on line 107
Warning: Cannot modify header information – headers already sent by (output started at /home/lovers/ftp/app/controllers/components/image_auth.php:107) in /home/lovers/ftp/app/controllers/components/image_auth.php on line 110
Warning: Cannot modify header information – headers already sent by (output started at /home/lovers/ftp/app/controllers/components/image_auth.php:107) in /home/lovers/ftp/app/controllers/components/image_auth.php on line 111
Warning: Cannot modify header information – headers already sent by (output started at /home/lovers/ftp/app/controllers/components/image_auth.php:107) in /home/lovers/ftp/app/controllers/components/image_auth.php on line 112
Warning: Cannot modify header information – headers already sent by (output started at /home/lovers/ftp/app/controllers/components/image_auth.php:107) in /home/lovers/ftp/app/controllers/components/image_auth.php on line 113
Warning: Cannot modify header information – headers already sent by (output started at /home/lovers/ftp/app/controllers/components/image_auth.php:107) in /home/lovers/ftp/app/controllers/components/image_auth.php on line 114
Warning: Cannot modify header information – headers already sent by (output started at /home/lovers/ftp/app/controllers/components/image_auth.php:107) in /home/lovers/ftp/app/controllers/components/image_auth.php on line 117
�PNG
Ohhh…this up is my problem…and I don’t know what I must do that this will working.
You need a true type font. put a some ttf font in vendors/image_auth/ , then modify the variable var $font to match the font name
I follow the instructions but I have a problem, I don’t get the image
oh wow, thanks for the code!
can you confirm that:
- the component should be included in the controller?
- this will work under php4?
- should the URL http://path to login controller/image_auth/ produce the image?
i can’t get this to work. i want it to appear in /users/register and have added url(‘/users/register/image_auth’)?>” /> to the register view. I have the TTF in /vendors/image_auth/.
I have added the imaget_auth function to the users controller and my register function looks like this:
function register()
{
$this->imageAuth->generate();
$this->set(‘username_error’, ‘Username must be between 6 and 40 characters.’);
if (!empty($this->data))
{
if ($this->User->validates($this->data))
{
if (! $this->imageAuth->check( $this->params['data']['text'] ))
{
echo ‘Wrong text entered’;
}
if ($this->User->findByUsername($this->data['User']['username']))
{
$this->User->invalidate(‘username’);
$this->set(‘username_error’, ‘User already exists.’);
} else {
$this->data['User']['password'] = md5($this->data['User']['password']);
$this->User->save($this->data);
$this->Session->write(‘user’, $this->data['User']['username']);
$this->redirect(‘/users/index’);
}
} else {
$this->validateErrors($this->User);
}
}
}
I also can’t get this to work. Although it does work if I alter it a bit and have it create an image on the filesystem:
imagejpeg($img, WWW_ROOT . ‘img/tmp/test.gif’);
then you just need to make sure that there is a tmp directory under the img dir in your webroot, and make sure that your webserver account has write permissions in that dir. Although it would be best if I could get it working as above, and have the image just streamed to the browser instead of having it stored on the filesystem and then pointing my views to it. Anyone get it working as above? It just gives me a blank image…
I also had the issue of the “Could not find/open font ” stated in a comment here. The problem was that this script by default looks into the cake vendor directory, and not the vendor directory in your apps dir (which is where I placed the TTF file). A simple change got that working for me also:
putenv(‘GDFONTPATH=’ . realpath(APP . ‘vendors/image_auth’));
that way the GDFONTPATH points to my vendors directory in my app dir.
i got this error what can i do.
The image “http://localhost/cake_php/tests/image_auth” cannot be displayed, because it contains errors.Please give me the solution.
To Jenson:
Make sure that you have your DEBUG definition set to 0 in config/core.php . Also, make sure the font file you have is OK. If you have DEBUG set to 1 and need to see what’s going on, make some other action in your controller that spits out an HTML link to image_auth.
Hey dude your code is messed up! Post it better!
iam not getting the solution to this message
Warning: imagettftext()
kindly help
Good Work. But i think you should use a code highlighter to stop those smilies showing.
the link to the image isn’t working anymore..
dfdsfdsf
nyeksadasdsa
in the name of allah
output:
in the name of allah
Warning: Cannot modify header information – headers already sent by (output started at /var/www/html/graphic.php:2) in /var/www/html/graphic.php on line 3
�PNG ��� IHDR������������UZ���PLTE����x�W���IDATH�������à�S��U�����<�MV%����IEND�B`�
program code
in the name of allah
output
n the name of allah
Warning: Cannot modify header information – headers already sent by (output started at /var/www/html/graphic.php:2) in /var/www/html/graphic.php on line 3
[...] как предыдущая. Этот компонент я нашёл в блоге Rossoft где вы наверняка сможете найти для себя много [...]
hey Janson have you got the solution to your problem..i am also getting the same error??
“The image http://localhost/tests/users/image_auth cannot be displayed because it contains errors”
Please help!!
Hello!
Very Interesting post! Thank you for such interesting resource!
PS: Sorry for my bad english, I’v just started to learn this language
See you!
Your, Raiul Baztepo
?
even i cant see what the iamge in your captch example