Главная / PHP и MySQL, Полезное / Создание юзабильной капчи на PHP с картинками

Создание юзабильной капчи на PHP с картинками

Приветствую Вас, дорогие друзья!

Сегодня мы рассмотрим и создадим с нуля оригинальную и юзабильную («дружественную» для пользователя) капчу на PHP. То есть, все наверняка встречали капчи, где прямо, так скажем, надо всё расшифровывать по буквам. Вот я лично не люблю такие капчи и по этому решил создать такую юзабильную и простую капчу. Ну что же, начнём…


Для начала разберемся с организацией файлов. Для данной работы нам понадобиться локальный сервер (например, Denwer). Создаём директорию с нашим проектом (например, captcha.loc) в которой будут следующие директории и файлы:

директория css -> style.css – файл стилей;

директория images -> apple.png, apricot.png, kiwi.png, lemon.png, orange.png – наши картинки для капчи;

файл .htaccess -> в данном случаем он нам понадобиться для дополнительного указания кодировки UTF-8;

файл index.php -> в нём мы и будем писать весь наш код.

И так – приступим.

ШАГ 1 – Создаём HTML-разметку:

Здесь идёт простая HTML-разметка. Единственный момент который может Вас насторожить, это: почему в скрытом поле (строка 33) атрибут value не заполнен? В атрибут value будет подставляться и сравниваться значение с тем, что выбрал пользователь, и тем сгенерированным значением, что было запомнено в сессии.

Файл .htaccess – это файл дополнительной конфигурации веб-сервера Apache. В нём всего одна строчка кода, в которой указывается кодировка нашего документа. Хотя в самом HTML-документе мы указали кодировку, но бывает такая ситуация, когда в самом браузере стоит кодировка Windows-1251 (кириллица), а в документа – UTF-8 – понятно, что документ будет отображаться в кодировке Windows-1251 (приоритет браузера выше), и для того, чтобы документ отображался в той кодировке что нам и нужно – служит файл .htaccess. В этом файле добавим строчку: AddDefaultCharset utf-8

<!DOCTYPE html>
<html>
<head>
 <meta http-equiv="Content-Type" content="text/html; charset=utf-8">
 <link rel="stylesheet" type="text/css" href="css/style.css">
  <title>Юзабильная капча с картинками</title>
 <!-- Подключаем jQuery-библиотеку -->
 <script type="text/javascript" src="//ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
 <!-- Здесь будет Наш дальнейший JavaScript код -->
</head>
<body>

<div class="form">

 <h2>Оставить комментарий:</h2>

 <form method="POST" action="">
   <label for="name">Ваше имя:</label><br />
   <input type="text" id="name" name="name" size="45" /><br />

   <label for="text">Введите сообщение:</label><br />
   <textarea name="text" id="text" rows="5" cols="33"></textarea><br />
   <p>Выберите <strong><?php echo $_SESSION['fruit']?>:</strong></p>

   <div class="captcha">
     <img src="images/apple.png" width="50px" height="50px" alt="яблоко">
     <img src="images/apricot.png" width="50px" height="50px" alt="абрикос">
     <img src="images/kiwi.png" width="50px" height="50px" alt="киви">
     <img src="images/lemon.png" width="50px" height="50px" alt="лимон">
     <img src="images/orange.png" width="50px" height="50px" alt="апельсин">
   </div>

   <input type="hidden" name="fruit" id="fruit" value="">
   <input type="submit" name="submit" id="submit" value="Отправить" />
 </form>
 <!-- Здесь будут выводиться данные -->

</div>

</body>
</html>

ШАГ 2 – Добавляем стили:

Правило !important (строка 14) - позволяет повысить приоритет стиля, т.е. это правило для нас будет важнее. Как результат, когда мы щёлкнем по картинке, то рамка останется.

.captcha {
  margin: 10px 0;
}
.captcha img {
  border: 1px solid #ccc;
  border-radius: 5px;
  cursor: pointer;
  margin-right: 5px;
}
.captcha img:hover, .active {
  -moz-box-shadow: 0 0 10px #808080;
  -webkit-box-shadow: 0 0 10px #808080;
  box-shadow: 0 0 10px #808080;
  border: 1px solid #7CFC00 !important;
}
/* стили для вывода конечного сообщения */
.ok, .not_ok {
  width: 285px;
  padding: 5px;
  margin: 10px 0;
  border-radius: 5px;
}
.ok {
  border: 1px solid #008000;
  background: #BAFAC1;
  color: #008000;
}
.not_ok {
  border: 1px solid #FF0000;
  background: #FFD5D5;
  color: #FF0000;
}

ШАГ 3 – Пишем код JavaScript:

Этот JavaScript код нужно вставлять межу тегами head.

Основная работа данного скрипта заключается в том, чтобы отслеживать клик по картинке и выполнять определенные действия.

И так, когда пользователь кликает по картинке, мы берем все картинки и методом each проходим по всем картинкам, и при клике по картинке скрипт будет добавлять класс active (то есть, просто будет устанавливаться зеленая рамка) и получать значение атрибута alt.

Если пользователь кликнет на другую картинку, то ей просто будет добавляться класс active, а для остальных картинок класс active - удаляется!

Дальше, мы обращаемся к тому элементу, по которому был клик и обращаемся к его атрибуту alt, потом помещаем его значение в переменную fruit, обращаемся к нашему скрытому полю с id=”fruit” и в его же значение записываем то, что есть в переменной fruit – это нужно для сравнения значений!

А в  строке 4 мы просто будем очищать значение скрытого поля, чтобы оно постоянно не запоминалось.

<script type="text/javascript">
 $(document).ready(function () {

  $("#fruit").val('');

  $(".captcha img").click(function() {
     $(".captcha img").each(function() {
     $(this).removeClass("active");
  });
     $(this).addClass("active");
     var fruit = $(this).attr("alt");
     $("#fruit").val(fruit);
  });

 });
</script>

ШАГ 4 – Пишем серверный (РНР) код:

Этот РНР код нужно вставлять в самом начале документа, то есть писать РНР код с первой же строки.

Замечание: пробелов и комментариев перед открытием РНР кода НЕ должно быть, иначе выдаст ошибку!

И так, мы создали массив fruits. Далее, генерируем случайный элемент массива fruits и его значение записывается в сессию. Потом проверяем не приходили ли нам данные из формы, то есть, ели данные из формы методом POST вообще НЕ приходили, то мы будем записывать в сессию случайный элемент (фрукт), а иначе мы принимаем данные из формы средствами РНР и будем сравнивать с теми, что у нас есть скрытом поле.

Затем получаем данные из полей формы и проверяем, если пользователь что-то ввел в поле, если ничего не ввел, мы просто его представляем как “Гость“.

Дальше мы должны сравнивать с тем, что у нас есть в сессии и что попало в скрытое поле. И если в глобальном массиве СЕССИЯ, элемент fruit будет равен тому что у нас есть в переменной fruit, то выводим сообщение типа:”Вы прошли проверку и т.д.”, а иначе, то есть, элемент fruit НЕ будет равен тому что у нас есть в переменной fruit, мы выводим сообщение типа:”Вы не прошли проверку и т.д.”.  Затем делаем редирект, чтобы сбросить POST-данные.

<?php
session_start();
$fruits = array("яблоко", "абрикос", "киви", "лимон", "апельсин");
$randNum = mt_rand(0,4);

if (!$_POST)
{
  $_SESSION['fruit'] = $fruits[$randNum];
}
else
{
  $name = trim(htmlspecialchars($_POST['name']));
  if (empty($name))
  {
     $name = "Гость";
  }
  $text = $_POST['text']; //текстовая облать
  $fruit = $_POST['fruit']; //скрытое поле

  if ($_SESSION['fruit'] == $fruit)
  {
    $_SESSION['result'] = "<div class='ok'>{$name}, Вы прошли проверку. Спасибо за комментарий!</div>";
    header("Location: {$_SERVER['PHP_SELF']}");
    exit();
  }
  else
  {
    $_SESSION['result'] = "<div class='not_ok'>{$name}, Вы не прошли проверку. Попробуйте ещё раз!</div>";
    header("Location: {$_SERVER['PHP_SELF']}");
    exit();
  }
}
?>

ШАГ 5 – Выводим информационное окно:

Этот маленький РНР код нужно вставить после формы.

<?php
if($_SESSION['result'])
{
  echo $_SESSION['result'];
  unset($_SESSION['result']);
}
?>

На этом всё!

Спасибо всем за внимание!

Ждём Ваших отзывов об уроке в комментариях.

Авторские права: webformyself.com


Обсуждение. Оставлено 27 коммент.

Спасибо, долго ждал)))

Дмитрий, спасибо!
Отличный и полезный урок!
Я еще просил вас создать урок по добавлению товара в корзину с помощью jQuery. на базе вашего мини урока по созданию интернет магазина.
Если Вас не затруднит.
Заранее благодарен!

Классно! Спасибо большое, очень хорошо все разжевано

Скачал исходники поставил на сервер, проверил почему-то не работает, выдает сообщение что я прошел проверку, даже если я отвечаю не верно или вообще не выбирал картинку? в чем дело?..

Как раз вовремя урок попался – только подумал о том, как можно капчу сделать

Исходники скачал и все заработало. Спасибо большое.

Спасибо, Дмитрий!

Очень пригодилась вот моя реализация данной капчи:
http://ketov.biz/kontakt/

Действительно всё очень просто на самом деле.

Спасибо, все работает на внешнем сервере, видимо причина в настройках моего локального сервера.

А я вот не поняла.
На ПК я все сделаю. Но на своем сайте у меня уже есть файл .htaccess. Что туда прописывать?
И, еще, данный комплект помещать в отдельной папке своего сайта? Потому, что у меня уже есть файлы с аналогичными названиями…
Поясните…
Кстати, я бы не прочь иметь такую капчу как у Вас: выбор одного из трех человечков.
Если можно. опишите данный вариант. Спасибо.

Алиса, в .htaccess добавьте строчку AddDefaultCharset utf-8.
Картинки можете помещать куда Вам угодно, главное потом пропишите правильно пути к данным картинкам.
Вместо фруктов можно использовать и человечков. Вам нужны другие картинки и немного поменять код. Вместо массива с фруктами создать массив с человечками и т.д.

Вордпресс-f1, спасибо большое за отзыв!

Alisa, в файл .htaccess просто добавьте строчку – AddDefaultCharset utf-8 , как написал Дмитрий выше.
В файл style.css просто добавьте те стили, что я написал в уроке.
Картинки просто перенесите в свою папку с картинками, но правильно укажите путь к ним.
Если что-то еще не понятно, то пишите здесь или мне на “мыло” – admin@bykandrey.ru

У меня есть сайт на локальном сервере (Denwer). Никак не могу сообразить где находиться этот файл style.css.
Прошу прощения за мою тупость.

Если речь идет о данном скрипте, то он находится в папке css.

Огромное спасибо!

Sergey, пользуйтесь на здоровье! Спасибо за комментарий ;)

Спасибо! Отличная стать! Заточил по похожему принципу капчу для codeigniter. Добавил ещё несколько картинок, плюс сделал примочку, – по наведению на картинку немного увеличивать её (onMouseOver и onMouseOut). Если кому интересно, пишите на aleksandro13-87@mail.ru, или возникнут вопросы, как подобную капчу сделать под поджигателя кода.

На Денвере все прекрасно работает! Спасибо! Но на хостинге
Рамка после клика не остается зеленой… и картинка не выбирается.
Подскажите в чем может быть причина?

Вот интересно, все стараются вынести скрипты из тега HEAD в конец – перед тегом , а Вы пишете -” Этот JavaScript код нужно вставлять межу тегами head”. Тогда надо прикручивать асинхронную загрузку.

Уважаемый теска, а это вы себе верстали тему для вашего блога и заказали у фрилансера?

Здравствуйте. Сайт верстал сам.

а можешь сделать курс(платн или бесплатн) по создния тем к wp?

У меня есть такой курс, но он сейчас отдельно не продается, только как дополнение к курсу “Сайтотворец – Прибыльный веб-сайт”

Привет. Капча выглядит красиво, но это не капча, и не потому, что реализация не совсем классическая, а потому что “обходится” за “5 секунд”.
1) картинки выводятся статически с определенной последовательностью и самое главное за определенной картиркой закреплено одно и то же имя, что позволяет без труда создать массив соответсвий.
2) у каждой картинки в alt прописаны так называемые ответы на вопрос
3) но в данной реализации капчи, даже на первые два пункта не надо обращать внимание, надо просто взять из лимон: название фрукта и вставить понятное дело куда.
Что можно сделать для доведения идеи “до ума”:
Картинки на сервере придется таки генеривовать “на лету”, ну или хотябы их имена. Это не означает, что каждый раз надо выдумывать новое мия, достаточно менять местами соответсвие имен с картинками. Но если добавить шума или искажений, то вроде как не повредит. Последовательность картинок надо менять с каждым обновлением страницы. Естественно на сервере в сессии хранить текущее соответсвие правильного ответа

Здравствуйте. Можете продемонстрировать свой вариант?

отправил на почту архивом

Будь любезен, кинь архив мне тоже, на почту zhiwanski@yandex.ru


Оставить комментарий

Этот домен продается здесь: telderi.ru, и еще много других