(CAPTCHA - это полностью автоматический тест Тьюринга для различения компьютеров и людей)
Устали от кодов, которые нужно каждый раз вводить? Если так и есть, пора научиться создавать CAPTCHA, на который надо лишь кликнуть мышью. Именно этому и будет посвящен наш сегодняшний урок.
Введение
Мы реализуем очень уникальный способ приведения в исполнение теста CAPTCHA. Одно из больших преимуществ подобного способа это отсутствие необходимости хранить на сервере сайта несколько сотен, а то и тысяч изображений.
Цель урока
Данный урок нацелен на создание CAPTCHA, по которому достаточно кликнуть курсором мыши. Давайте назовем его клик- CAPTCHA.
Изображение CAPTCHA будет отображаться в форме, тогда как маска будет храниться на сервере сайта. Маска на самом деле всего лишь копия изображения CAPTCHA, только без орнамента. Дело в том, что маска позволит нам распознать цвет каждого пикселя. Вы все поймете сами дальше.
Шаг 1: Создайте свой captcha.php
Сразу же хочу сказать, что мы не будем использовать шрифты в этом уроке, мы лишь воспользуемся GD библиотекой, чтобы представить тест CAPTCHA.
Итак, давайте создадим captcha.php.
В нашем скрипте, мы запустим сеанс соединения с сервером с помощью свойства session_start() и укажем параметры переменных $width и $height.
<?php
// запуск сеанса
session_start();
// параметры переменных
$width = 180;
$height = 90;
$blob_width = 40;
$blob_height = 40;
?>
Шаг 2: Содержимое изображения
На этом этапе, мы создадим содержимое изображения, а именно красный круг с орнаментом. Это задача выполняется с помощью функции imagecreatetruecolor().
// содержимое изображения
$image = imagecreatetruecolor($width, $height);
Привяжем параметры переменной цвета к элементу $image:
// фоновый цвет изображения
$white = imagecolorallocate($image, 230, 230, 230);
$red = imagecolorallocate($image, 255, 0, 0);
$blue = imagecolorallocate($image, 0, 0, 230);
Теперь закрасим белым цветом:
// наполняем изображение
imagefilledrectangle($image, 0, 0, $width, $height ,$white);
И наконец, создаем орнамент в виде спирали для фона нашего изображения.
// создаем орнамент в форме спирали
$theta = 1;
$thetac = 7;
$radius = 16;
$circles = 20;
$points = 32;
for ($i = 0; $i < ($circles * $points) - 1; $i++)
{
$theta = $theta + $thetac;
$rad = $radius * ($i / $points );
$x = ($rad * cos($theta)) + $x_axis;
$y = ($rad * sin($theta)) + $y_axis;
$theta = $theta + $thetac;
$rad1 = $radius * (($i + 1) / $points);
$x1 = ($rad1 * cos($theta)) + $x_axis;
$y1 = ($rad1 * sin($theta )) + $y_axis;
imageline($image, $x, $y, $x1, $y1, $blue);
$theta = $theta - $thetac;
}
Шаг 3: Кружок и Маска
Теперь мы нарисуем красный круг и создадим его маску-копию.
Кружок:
Сперва выберем местоположение кружка на создаваемом шаблоне, а затем выведем его на изображении нашего CAPTCHA с помощью свойства imagefilledellipse().
// указываем расположение кружка
$x_axis = rand($blob_width, $width) - ($blob_width / 2);
$y_axis = rand($blob_height, $height) - ($blob_height / 2);
Укажем, что цвет будет красный (как было оговорено ранее).
// выводим кружок на изображение
imagefilledellipse ($image, $x_axis, $y_axis, $blob_width, $blob_height, $red);
Маска:
Почти так же как и в шаге 2 с помощью свойства imagecreatetruecolor() мы создаем маску-копию.
// создаем маску
$mask_image = imagecreatetruecolor($width, $height);
Снова задаем цветовые параметры переменной color для кружка и для фона изображения. Размещая красный кружок, указываем те же самые координаты что и для круга на изображении CAPTCHA.
// фоновый цвет маски
$mask_white = imagecolorallocate($mask_image, 255, 255, 255);
$mask_red = imagecolorallocate($mask_image, 255, 0, 0);
// заполняем содержимым изображение
imagefilledrectangle($mask_image, 0, 0, $width, $height ,$mask_white);
// размещаем кружок на изображении
imagefilledellipse ($mask_image, $x_axis, $y_axis, $blob_width, $blob_height, $mask_red);
Шаг 4: Сохраняем созданную маску на сервере
Чтобы наш тест работал, необходимо сохранить маску в данную сессию сервера. Для этого нужно сначала вывести слой-маску куда-нибудь, а прежде, чем сохранить в нашу сессию, нужно извлечь его в виде первичных данных.
Итак воспользуемся свойством ob_start(), чтобы активизировать буферизацию на выходе и записать данные случайным образом/виртуально.
// сохраняем маску в буфер
ob_start();
Теперь выводим маску используя свойство imagepng().
imagepng($mask_image);
Возвращаем маску в виде первичных данных с помощью свойства ob_get_contents(), которое извлекает содержимое буфера уже в виде одной строки.
$mask_image_data = ob_get_contents(); // извлекаем то, что сохранили в буфер
Преобразовываем полученные из буфера данные в Base64, так как нам нужно создать код понятный серверу.
// преобразуем данные в Base64
$mask_image_data_b64 = base64_encode($mask_image_data);
И наконец, сохраняем полученное в сессии.
Шаг 5: Выведем полученное в браузер!
На этом этапе мы выведем CAPTCHA в браузер. Для этого нам необходимо указать тип содержимого, так чтобы браузер распознал и отобразил все должным образом.
// Указываем тип
header('Content-type: image/jpeg');
header('Cache-control: no-cache');
// вывод изоражения
imagejpeg($image);
imagedestroy($image);
Давайте, наконец, все сохраним и откроем в браузере!
Шаг 6: Создаем форму
Давайте создадим новый PHP script и назовем его index.php. Страница будет содержать форму, которую мы подтвердим используя созданный нами CAPTCHA.
HTML код:
Замените кнопку Submit кнопкой с Image. В примере я дам ей имя ’submit’, но вы можете назвать ее как душе угодно.
<form action="<?php echo $_SERVER['PHP_SELF']; ?>" method="post" enctype="multipart/form-data">
<p>Name<br/><input type="text" name="name" /></p>
<p>Comment<br/><textarea name="message"></textarea></p>
<p>
Click the Red Circle to continue:<br/>
<input type='image' name='submit' src='captcha.php' alt='Captcha Security' />
</p>
</form>
В браузере код должен выглядеть следующим образом:
Шаг 7: Подтвердим форму!
Раз все работает и CAPTCHA отображается как положено, требуется задать функцию подтверждения формы.
Ключевые параметры PHP кода для подтверждения формы следующие:
1. session_start()
2. $_POST['submit_x'] and $_POST['submit_y']
3. Распознавание цвета точки –клика.
В этот же код мы добавим контроль правильности заполнения полей формы. И уточним X и Y координаты области рисунка, в которую нужно попасть :) курсором.
session_start();
if(isset($_POST['submit_x']) && isset($_POST['submit_y'])) {
if(!empty($_POST['name']) && !empty($_POST['message'])) {
// retrive the image captcha data
$data = base64_decode($_SESSION['captcha_image_code']);
$captcha_image = imagecreatefromstring($data);
$x = $_POST['submit_x'];
$y = $_POST['submit_y'];
// get the pixel color of the clicked x and y coordinate
$rgb = imagecolorat($captcha_image, $x, $y);
$color_tran = imagecolorsforindex($captcha_image, $rgb);
// check if the color is red and red only
$captcha_ok = ($color_tran['red'] == 255 && $color_tran['green'] == 0 && $color_tran['blue'] == 0 && $color_tran['alpha'] == 0) ;
if($captcha_ok) {
$result = "Thank you for submitting your comment.";
} else {
$result = "Please make sure you click the red circle!"; }
} else {
$result = "Please fill out the entire form.";
}
}
Чтобы установить цвет и координаты кликнутого пикселя, необходимо сперва извлечь изображение маски из сохраненной сессии, а затем декодировать его как показано ниже:
// извлекаем данные изображения CAPTCHA
$data = base64_decode($_SESSION['captcha_image_code']);
Преобразуем его обратно в изображение используя функцию imagecreatefromstring().
$captcha_image = imagecreatefromstring($data);
Теперь извлекаем X и Y координаты клика и цвет кликнутого пикселя с помощью imagecolorsforindex(). Нужно убедиться, что цвет точки именно красный.
// получаем цвет точки клика
$rgb = imagecolorat($captcha_image, $x, $y);
$color_tran = imagecolorsforindex($captcha_image, $rgb);
// проверка действительно ли цвет точки именно красный
$captcha_ok = ($color_tran['red'] == 255 && $color_tran['green'] == 0 && $color_tran['blue'] == 0 && $color_tran['alpha'] == 0) ;
Свойство $captcha_ok помогает понять в то ли место кликнул пользователь.
ГОТОВО!!! Теперь у вас есть уникальный тест CAPTCHA. Надеюсь вам понравился урок