- PVSM.RU - https://www.pvsm.ru -
На работе потребовалось решить проблему со спамом, так как старую капчу легко обходили спамботы. Погуглив и не найдя нужных вариантов, решил написать свой, да и давно хотелось, если честно.
И так, суть капчи в том, что пользователю отображается несколько иконок и необходимо выбрать ту, которая логически не вписывается в общий ряд. Думаю в интернете таких вариантов море, но я не нашел (ну если честно не особо то и искал).
Принцип работы следующий: собирается две группы иконок, одна это массив с правильными вариантами, другая с неправильным. Собирается в общий массив, при этом ключ неправильной картинки (порядковый номер элемента массива) записывается в сессию.
Из всех иконок собираем одно изображение, которое потом будем резать с помощью background-position.
Форма представляет собой радиокнопки с value от 1 и до количества иконок. Отправляем с помощью POST форму с нажатым value и сверяем его с тем числом, что мы положили в сессию, все довольно просто.
И так, есть директория, где лежат группы иконок:
Весь функционал реализован в одном классе. Разберем поподробнее:
private $icon_dir; //директория, где лежат папки с иконками
private $icon_size; //размер иконки
private $first_group_num; //номер первой группы иконок
private $second_group_num; //номер второй группы иконок
private $icon_count; //количество отображаемых в капче иконок
private $group_count; //количество групп иконок
private $address; //адрес, по которому будет генерироваться капча
function __construct($icons_count, $icon_dir, $icon_size, $address)
{
$this->icon_dir = $icon_dir;
$this->icon_size = $icon_size;
$this->group_count = scandir($this->icon_dir);
$this->group_count = count($this->group_count) - 2;
$this->first_group_num = rand(1, $this->group_count);
$this->second_group_num = rand(1, $this->group_count);
$this->icon_count = $icons_count;
while ($this->first_group_num == $this->second_group_num) {
$this->second_group_num = rand(1, $this->group_count);
}
$this->address = $address;
}
$_SESSION['iconcaptcha'] = array_search($true_icon, $array_of_icons) + 1;
где $true_icon — искомая нами иконка, а $array_of_icons конечный массив с иконками.
private function makeSprite()
{ //соединим иконки в одно изображение
$icons = array();
$array_of_icons = $this->getArrayOfIcons();
for ($i = 0; $i < $this->icon_count; ++$i) {
$icons[] = imagecreatefrompng($array_of_icons[$i]);
}
//для прозрачности png
$tmp_sprite = imagecreatetruecolor($this->icon_count * $this->icon_size, $this->icon_size);
imagealphablending($tmp_sprite, false); imagesavealpha($tmp_sprite, true);
$tmp_icon = imagecreatetruecolor($this->icon_size, $this->icon_size);
imagealphablending($tmp_icon, false); imagesavealpha($tmp_icon, true);
foreach ($icons as $key => $val) {
imagecopyresampled($tmp_icon, $val, 0, 0, 0, 0, $this->icon_size, $this->icon_size, $this->icon_size, $this->icon_size);
imagecopy($tmp_sprite, $tmp_icon, $key * $this->icon_size, 0, 0, 0, imagesx($tmp_icon), imagesy($tmp_icon));
}
header("Content-type: image/png");
imagepng($tmp_sprite);
imagedestroy($tmp_sprite);
exit;
}
private function getCaptchaAddress($address)
{ //получим изображение по адресу $address
$req = end(explode('/', $_SERVER['REQUEST_URI']));
$req = explode('?', $req);
if ($req[0] == $address) $this->makeSprite();
}
function getCaptchaForm()
{
$this->getCaptchaAddress($this->address);
$captcha_form = '<style>
#icon_captcha label div {
background-image: url(/'.$this->address.'?'.rand().');
width: '.$this->icon_size.'px;
height: '.$this->icon_size.'px;
}
#icon_captcha {
margin-bottom: 20px !important;
display: table !important;
}
#icon_captcha div {
width: '.$this->icon_size.'px;
display: inline-block;
margin-right: 20px;
}
#icon_captcha div input {
width: '.$this->icon_size.'px;
margin-left: 0;
float: left;
border: none;
}
#icon_captcha div label img {
border: none;
}
</style>
<div id="icon_captcha">';
for ($i = 1; $i <= $this->icon_count; ++$i) {
$captcha_form .= '<div>
<label for="val_'.$i.'">
<div class="i'.$i.'" style="background-position: '
.(($i - 1)*(-$this->icon_size)).
'px 0;"></div>
</label>
<input type="radio" name="radio_val" id="val_'.$i.'" value="'.$i.'" />
</div>';
}
$captcha_form .= '</div>';
return $captcha_form;
}
Вот как выглядит вызов на одном из примеров, происходит это дело в конфигурационном файле:
require(INC_DIR.'libs/IconCaptcha.class.php');
$icon_dir = $_SERVER['DOCUMENT_ROOT']."/design/site/images/captcha/";
$icon_captcha = new IconCaptcha(4, $icon_dir, 32, 'iconcaptcha');
$captcha_form = $icon_captcha->getCaptchaForm();
define('ICONCAPTCHA', $captcha_form);
Далее просто подставляем ICONCAPTCHA в нужную нам форму, а проверяем ее банальным сравнением: $_POST[‘radio_val’] == $_SESSION[‘iconcaptcha’].
Тут можно пощелкать демо: iconcaptcha.hut4.ru/ [1]
Тут посмотреть класс целиком: github.com/L1Qu0R/iconcaptcha/blob/master/IconCaptcha.class.php [2]
Автор: L1Qu0R
Источник [3]
Сайт-источник PVSM.RU: https://www.pvsm.ru
Путь до страницы источника: https://www.pvsm.ru/web-razrabotka/32919
Ссылки в тексте:
[1] iconcaptcha.hut4.ru/: http://iconcaptcha.hut4.ru/
[2] github.com/L1Qu0R/iconcaptcha/blob/master/IconCaptcha.class.php: https://github.com/L1Qu0R/iconcaptcha/blob/master/IconCaptcha.class.php
[3] Источник: http://habrahabr.ru/post/177805/
Нажмите здесь для печати.