Капча для сайта с использованием PHP, Bootstrap, jQuery и AJAX

Статья, в которой наглядно рассмотрим процесс создания своей собственной простой CAPTCHA в форме с использованием PHP, Bootstrap, jQuery и AJAX.
Что такое CAPTCHA
CAPTCHA (капча) – это простой тест, предназначенный для того, чтобы отличить человека от компьютера. Т.е. это такой тест, который человек решает легко, а компьютер научить его выполнять крайне сложно.
CAPTCHA используется для того, чтобы на сайте или блоге предотвратить выполнение компьютером (программами) различных действий: выполнения регистраций, отправления сообщений, скачиваний материалов и много другого. Т.е. иметь гарантию того, что действия выполняются людьми, а не роботами.
В большинстве случаев CAPTCHA отображается как некоторый искаженный или наложенный на фон текст (код), который посетителю сайта необходимо разобрать и ввести его в некоторое поле. Кроме текста (кода) используется и другие алгоритмы: найти среди множества картинок правильные, собрать пазл, переместить слайдер, нарисовать связь между несколькими картинками и др.
Создание CAPTCHA с помощью PHP, Bootstrap, jQuery и AJAX
Разрабатывать CAPTCHA (капчу) будем для формы регистрации, расположенной в модальном окне. Данная форма будет состоять из двух полей: логина и email. Создадим форму и модальное окно с использованием классов и компонентов платформы Twitter Bootstrap 3.
Файл index.html
:
<html lang="ru"> <head> <meta charset="utf-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1"> <title>Валидация формы с captcha</title> <link rel="stylesheet" type="text/css" href="css/bootstrap.min.css" /> </head> <body> <!-- Модальное окно --> <div id="myModal" class="modal fade" tabindex="-1" role="dialog"> <div class="modal-dialog"> <div class="modal-content"> <!-- Заголовок модального окна --> <div class="modal-header"> <button type="button" class="close" data-dismiss="modal">×</button> <h4 class="modal-title" id="myModalLabel">Регистрация</h4> </div> <!-- Основная часть модального окна, содержащая форму для регистрации --> <div class="modal-body"> <!-- Форма для регистрации --> <form id="myForm" method="post" role="form" name="myForm"> <!-- Блок для ввода логина --> <div class="form-group has-feedback"> <label for="login" class="control-label">Введите логин:</label> <div class="input-group"> <span class="input-group-addon"><i class="glyphicon glyphicon-user"></i></span> <input type="text" class="form-control" required="required" name="login" pattern="[A-Za-z]{6,}" value=""> </div> <span class="glyphicon form-control-feedback"></span> </div> <!-- Блок для ввода email --> <div class="form-group has-feedback"> <label for="email" class="control-label">Введите email:</label> <div class="input-group"> <span class="input-group-addon"><i class="glyphicon glyphicon-envelope"></i></span> <input type="email" class="form-control" required="required" name="email" value=""> </div> <span class="glyphicon form-control-feedback"></span> </div> <!-- Конец блока для ввода email--> <hr> <!--Изображение, содержащее код CAPTCHA--> <img id="img-captcha" src="captcha.php"> <!--Элемент, запрашивающий новый код CAPTCHA--> <div id="reload-captcha" class="btn btn-default"><i class="glyphicon glyphicon-refresh"></i> Обновить</div> <!--Блок для ввода кода CAPTCHA--> <div class="form-group has-feedback"> <label id="label-captcha" for="captcha" class="control-label">Пожалуйста, введите указанный на изображении код:</label> <input id="text-captcha" name="captcha" type="text" class="form-control" required="required" value=""> <span class="glyphicon form-control-feedback"></span> </div> </form> </div> <!-- Нижняя часть модального окна --> <div class="modal-footer"> <button type="button" class="btn btn-default" data-dismiss="modal">Отмена</button> <button id="save" type="button" class="btn btn-primary">Регистрация</button> </div> </div> </div> </div> <div class="container"> <div class="alert alert-success hidden" id="success-alert"> <h2>Успех</h2> <div>Ваши данные были успешно отправлены.</div> </div> <!-- Кнопка для открытия модального окна --> <button id="btn-modal" type="button" class="btn btn-lg btn-success" data-toggle="modal" data-target="#myModal"> Регистрация </button> </div> <script src="js/jquery-2.1.4.min.js" type="text/javascript"></script> <script src="js/bootstrap.min.js" type="text/javascript"></script> </body> </html>
Принцип работы создаваемой CAPTCHA изобразим на следующем рисунке:
Формировать код CAPTCHA будем на сервере с помощью файла captcha.php
. В этом файле мы создадим переменную captchastring
, которая будет состоять из цифр, строчных и прописных букв латинского алфавита. Создавать случайный код будем посредством перемешивания этих букв и цифр с помощью PHP функции str_shuffle()
и последующего извлечения из полученной строки первых 6 символов. Полученная подстрока будет являться CAPTCHA кодом, которую сохраним в эту же переменную (captchastring
). После этого будем хранить код CAPTCHA в переменной сессии code
.
Чтобы передать CAPTCHA код в форму, его предварительно необходимо защитить от роботов, т.е. сделать так, чтобы его мог прочитать только человек. Для этого возьмем некоторый фон (background.png
) и напишем на нём с помощью некоторого шрифта код. Полученное изображение будем использовать для передачи его в форму.
Файл captcha.php
:
<?php //открывает сессию session_start(); //присваивает PHP переменной captchastring строку символов $captchastring = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890abcdefghijklmnopqrstuvwxyz'; //получает первые 6 символов после их перемешивания с помощью функции str_shuffle $captchastring = substr(str_shuffle($captchastring), 0, 6); //инициализация переменной сессии с помощью сгенерированной подстроки captchastring, //содержащей 6 символов $_SESSION["code"] = $captchastring; //Генерирует CAPTCHA //создает новое изображение из файла background.png $image = imagecreatefrompng('background.png'); //устанавливает цвет (R-200, G-240, B-240) изображению, хранящемуся в $image $colour = imagecolorallocate($image, 200, 240, 240); //присваивает переменной font название шрифта $font = 'oswald.ttf'; //устанавливает случайное число между -10 и 10 градусов для поворота текста $rotate = rand(-10, 10); //рисует текст на изображении шрифтом TrueType (1 параметр - изображение ($image), //2 - размер шрифта (18), 3 - угол поворота текста ($rotate), //4, 5 - начальные координаты x и y для текста (18,30), 6 - индекс цвета ($colour), //7 - путь к файлу шрифта ($font), 8 - текст ($captchastring) imagettftext($image, 18, $rotate, 28, 32, $colour, $font, $captchastring); //будет передавать изображение в формате png header('Content-type: image/png'); //выводит изображение imagepng($image); ?>
Проверять CAPTCHA код, который ввёл пользователь, будем в файле verify.php
на сервере. Осуществлять это будем посредством сравнения значения хранящейся в переменной сессии code ($_SESSION["code"]
) и значения $_POST["captcha"]
. В качестве результата сравнения будем возвращать строку true
, если данные соответствуют или false
, если данные не соответствуют.
Файл verify.php
:
<?php //открывает сессию session_start(); //проверяет соответствие коду CAPTCHA if ($_SESSION["code"] == $_POST["captcha"]) { //сообщаем строку true, если код соответствует echo 'true'; } else { //сообщаем строку false, если код не соответствует echo 'false'; } ?>
Последним этапом разработки формы с CAPTCHA является создание кода JavaScript с применением библиотеки jQuery и AJAX.
Данный код будет выполнять следующее:
- выводить новый код CAPTCHA при открытии модального окна;
- выводить новый код CAPTCHA при нажатии на кнопку "Обновить";
- выполнять валидацию полей формы "Логин" и "Email" с помощью HTML5 функции
checkValidity()
; - визуально выделять поля формы, которые прошли и не прошли валидацию;
- отправлять на проверку код CAPTCHA, который ввёл пользователь на сервер через AJAX в файл
verify.php
и получать от него результат. Если результат положительный и форма валидна, то код будет скрывать модальное окно и отображать сообщение об успехе. А если результат отрицательный, то код будет выделять поле, содержащее код CAPTCHA, который ввёл пользователь, красным цветом и значком "Ошибка".
Код JavaScript, который необходимо поместить в отдельный файл и подключить к нужным страницам (для демонстрации поместим его в конец файла index.html
):
$(function() { //выводит новый код CAPTCHA при открытии модального окна $('#myModal').on('show.bs.modal', function () { $('#img-captcha').attr('src', 'captcha.php?id='+Math.random()+''); }); //выводит новый код CAPTCHA при нажатии на кнопку Обновить $("#reload-captcha").click(function() { $('#img-captcha').attr('src', 'captcha.php?id='+Math.random()+''); }); //при нажатии на кнопку Регистрация (id="save") $('#save').click(function() { //переменная formValid var formValid = true; //перебирает все элементы управления input, кроме CAPTCHA $('input').each(function() { //если текущий элемент CAPTCHA, то пропустить его if ($(this).attr('id') == 'text-captcha') { return true; } //найти предков, которые имеют класс .form-group, для установления success/error var formGroup = $(this).parents('.form-group'); //найти glyphicon, который предназначен для показа иконки успеха или ошибки var glyphicon = formGroup.find('.form-control-feedback'); //для валидации данных используем HTML5 функцию checkValidity if (this.checkValidity()) { //добавить к formGroup класс .has-success, удалить has-error formGroup.addClass('has-success').removeClass('has-error'); //добавить к glyphicon класс glyphicon-ok, удалить glyphicon-remove glyphicon.addClass('glyphicon-ok').removeClass('glyphicon-remove'); } else { //добавить к formGroup класс .has-error, удалить .has-success formGroup.addClass('has-error').removeClass('has-success'); //добавить к glyphicon класс glyphicon-remove, удалить glyphicon-ok glyphicon.addClass('glyphicon-remove').removeClass('glyphicon-ok'); //отметить форму как не валидную formValid = false; } }); //проверяем элемент input, в который пользователь вводит код CAPTCHA //получаем значение элемента input, содержащего код CAPTCHA var captcha = $("#text-captcha").val(); //если код CAPTCHA пустой, то сразу сообщаем, что он не правильный if (captcha=='') { inputCaptcha = $("#text-captcha"); formGroupCaptcha = inputCaptcha.parents('.form-group'); glyphiconCaptcha = formGroupCaptcha.find('.form-control-feedback'); formGroupCaptcha.addClass('has-error').removeClass('has-success'); glyphiconCaptcha.addClass('glyphicon-remove').removeClass('glyphicon-ok'); } //иначе запрашиваем результат у сервера через ajax else { var dataString = 'captcha=' + captcha; $.ajax({ type: "POST", url: "verify.php", data: dataString, success: function(result) { inputCaptcha = $("#text-captcha"); formGroupCaptcha = inputCaptcha.parents('.form-group'); glyphiconCaptcha = formGroupCaptcha.find('.form-control-feedback'); //если результат, который вернул сервер, равен true, //то отмечаем, что код валидный и изменяет цвет элементов на зелёный if (result==="true") { formGroupCaptcha.addClass('has-success').removeClass('has-error'); glyphiconCaptcha.addClass('glyphicon-ok').removeClass('glyphicon-remove'); if (formValid) { //скрыть модальное окно $('#myModal').modal('hide'); //отобразить сообщение об успехе $('#success-alert').removeClass('hidden'); $('#success-alert').removeClass('hidden'); } } //иначе отмечает, что код не валидный и изменяет цвет элементов на красный else { formGroupCaptcha.addClass('has-error').removeClass('has-success'); glyphiconCaptcha.addClass('glyphicon-remove').removeClass('glyphicon-ok'); } } }); } }); });
На следующем изображении отображена не валидная форма:
На этом изображении отображена форма, у которой все поля, заполненные пользователем, валидны:
Наконец поняла, как вставлять в html-форму созданное в php изображение.
Для этого необходимо добавить на страницу с формами (для каждого изображения) при запросе капчи GET параметр:
И соответственно изменить название полей input, в которые пользователь будет их вводить:
На сервере при генерации изображения необходимо проверять наличие GET параметра и формировать изображения уже с учётом него:
Для валидации формы на стороне сервера соответственно это учитывать:
Инструкцию по реализации своей капчи для MODX (для указанных выше компонентов) опубликую немного позже (в виде отдельной статьи).
Второй момент — это необходимо проверить то, что из html файла Вы указываете правильный путь до captcha.php.
Ознакомиться с отличием в указание путей в JavaScript и PHP можно в статье «PHP — Корневая директория сайта».
Добавьте в код JavaScript строчку:
После этого посмотрите, с чем вы его сравниваете.
В статье возвращение true или false приведено для примера. Может вы что-то ещё выводите в процессе выполнения php-скрипта…
Спасибо за подробный разбор!
А как можно сделать, чтобы с помощью данной формы происходила регистрация нового пользователя?
Класс пользователей users уже создал и права им определил! И как чтобы информация из указанной формы переносилась в базу?
Начать можно делать так: