Как сделать каптчу на php

Здравствуйте, товарищи! Данная статья посвящена защите от различного рода ботов, которые так и шарятся по вашим страницам, норовя где-нибудь запостить какую-нибудь гадость. Не имеет значения, куда вы эту защиту приделаете: к форме комментирования, отправки сообщения или голосования - я думаю вы не любитель почитать спам на досуге :)

Сразу оговорюсь, заметка эта для начинающих php-кодеров, и я не буду описывать здесь сложные вещи с выводом текста на картинку, замутнение и искажение её и т.п. Но суть вопроса я вам разъясню ;)

Итак, поехали. Нам понадобится всего два файла, пусть это будут index.php и captcha.php (мы вполне могли обойтись и одним, но для удобства я решил код каптчи вынести в отдельный файл, а потом подключать его, где необходимо, просто чтобы он лишнее место не занимал).

Наша каптча будет представлять собой задачку, например, следующего вида: 
2 + 3 - 5 = ?
притом, числа всегда разные, операции также наугад берутся и по-разному отображаются. Для этого воспользуемся функциями rand() и srand().

Я не буду писать не по теме, так что если вы не знаете, для чего нужна функция srand(), можете почитать здесь: http://www.php.net/manual/ru/function.srand.php

Еще есть функция mt_rand(). Занятная статейка для сравнения функций rand() и srand() есть здесь: http://tjl.co/blog/code/followup-php-rand-vs-mt_rand/

Алгоритм состоит в следующем:

нам нужно две переменные, одна пусть будет $total, в которой будет сохранен ответ на задачку, вторая - $task, будет строкой, самим текстом задачки; затем мы получаем случайное число, и $total автоматически принимает его значение, а потом 2 раза делаем случайную операцию (сложение или вычитание) с переменной $total, т.е. в зависимости от результата функции rand() мы либо отнимаем, либо прибавляем опять же случайное число, попутно дописывая визуальное отражение наших операций переменной $task.

Ниже я привожу код файла captcha.php:

<?php

$sign[1] = array(
 '+', 'plus', 'плюс', 'прибавить'
 );

$sign[2] = array(
 '-', 'minus', 'минус', 'отнять'
 );

// т.е. получается, что $sign - двумерный массив

$numbers = array(
 'ноль', 'один', 'два', 'три', 'четыре', 'пять', 'шесть', 'семь', 'восемь', 'девять'
 ); // буквенные варианты чисел

function make_seed()
{
 list($usec, $sec) = explode(' ', microtime());
 return (float) $sec + ((float) $usec * 100000);
}

srand(make_seed()); // в принципе эту функцию можно не использовать, если хотите, тогда и функция make_seed() не нужна будет

$total = $num = rand(0, 9); // $total - ответ, который мы получим в результате, $num - случайное число от 0 до 9

$task = " $num "; // строка, в которой мы получаем визуальное отображение примера

for ( $i = 1; $i <= 2; $i++ ) // у нас 2 операции, поэтому $i <= 2. А вообще можно делать хоть 10 операций, тогда $i <= 10 будет
{
 srand(make_seed());
 
 $s = rand(1, 2); // какой знак: + или -
 $signview = rand(0, 3); // какой вид у знака
 
 $num = rand(0, 9); // случайное число от 0 до 9
 $numview = rand(1, 2); // вид числа: цифрой или буквами
 
 $total = ( $s == 1 ) ? $total + $num : $total - $num ; // если знак +, то прибавляем, и наоборот
 
 $num = ( $numview == 1 ) ? $num : $numbers[$num] ; // если буквами, то берем значение из массива $numbers
 
 $task .= " {$sign[$s][$signview]} $num "; // обратите внимание, что здесь не просто "присвоить", а именно оператор конкатенации
}
?>
 

Ну а теперь разберемся с кодом нашей основной страницы index.php. Между тэгами body разместим форму примерно такого содержания:

 

  
<form action="index.php" method="post">
<h2>Ля ля ля?</h2>
<p><strong>Ответ:</strong> <input type="text" name="var" value="La la la" /> <em>* пишите, что хотите</em></p>

<!-- Наша каптча -->
<p><strong>Решите задачку:</strong> <?= $task ?></p> 
<p><input type="text" name="captcha" value="" /></p>
<!-- Каптча закончилась -->

<p><input type="submit" /></p>
</form>
 

Как видите, там у нас в месте, где должна выводиться задачка, стоит переменная $task. Все правильно! :) Эту переменную мы получаем в файле captcha.php, который сейчас и будем подключать.

Идем в самый верх страницы, и в самое начало, еще до тэга <html> вставляем следующий php-код:

  
<?php

session_start(); // считываем все сессионные переменные и куки

// получаем каптчи из сессии (из массива сеансовых переменных то есть)
$sess = $_SESSION['capt']; // чуть ниже по тексту мы еще установим куки с таким именем, а в первый запуск он скорее всего будет пустым :)

// запускаем наш скрипт
include('captcha.php');

$true = 0; // это так просто

// проверяем, отправлял ли кто-нибудь нам что-либо, и не пустой ли куки каптчи
if ( !empty($_POST['var']) and !empty($sess) )
{
 $var = htmlspecialchars($_POST['var']); // этот var вообще к делу не относится и нафиг здесь не нужен, но надо же было что-то написать. Кстати, всегда помните о безопасности отправляемых вам данных, например, я неспроста использовал функцию htmlspecialchars, а если вы имеете дело с базами данных, то вот эта функция очень полезна mysql_real_escape_string
 
 $captcha = $_POST['captcha']; // а здесь мы строку не обрабатываем, потому как мы ее вводить никуда не будем, и нам по большому счету наплевать, что туда написали
 
 if ( $captcha == $sess ) // проверяем, правильно ли введена каптча
 {
 // Делаем все, что мы хотели делать с $var
 
 $true = 1;
 }
}

$_SESSION['capt'] = $total; // учтите, что всякие куки должны ставиться до того, как на страницу начнет выводиться какой-либо текст, иначе куки не поставится, подробнее можете почитать об этом погуглив по запросу "http headers"

?>
 

Вуаля! :)

Мы могли бы использовать больше операторов, например еще "умножить" и "разделить", или еще какую штуку придумать, тогда массив $sign был бы еще чуть более многомерным :) 

Работающий пример можно глянуть здесь. Скачать исходник можно здесь.

Я надеюсь, что вы все поняли и чему-то новому да научились. А если вы хоть чего-то не поняли, напишите комментарий, я все разъясню. Адьес! 

 Жду с нетерпением
ваших комментариев!
 

Подписаться на RSS

Вы можете нажать "подписаться", чтобы следить за моими новостями!
Так вы всегда будете в курсе появления новостей на сайте =)
О том, что такое RSS можно прочитать здесь.

Подписаться

Подписаться на Twitter

Я специально зарегистрировался в Твиттере, чтобы вы могли следить за обновлениями на сайте =)

Подписаться

Envato marketplace А эти люди занимаются прокатом карнавальных костюмов и масок в Минске. К слову, я им делал сайт.