простая капча на php
Капча на PHP
Капчу на PHP, или проверочный код, позволяющий отличить человека от робота, каждый из Вас вводил многократно: при регистрации, при отправлении сообщения, при поиске на сайте и много, где ещё. И в этой статье мы с Вами разберём скрипт, реализующий капчу на PHP, а также я Вам покажу, как использовать данный скрипт.
Сначала скачайте скрипт капчи на PHP. Извлекайте архив и помещайте его на Ваш сайт.
Теперь о том, как добавить капчу на форму, например, на форму регистрации:
В результате, на форме регистрации Вы увидите проверочный код, который пользователь должен будет ввести. Теперь о том, как проверить правильность ввода. Для этого в файле «register.php» (или в другом файле, который указан в атрибуте «action«) пишем следующие строки:
То есть считываем то, что ввёл пользователь ($_POST[‘kapcha’]) и сравниваем с тем, что находится в сессии (данное значение было записано при генерации капчи). Если значения не совпадают, то делаем вывод, что капча введена неправильно, иначе делаем вывод, что капча введена верно. То есть дальше Вы можете, основываясь на результат сравнения выполнить определённые действия. Например, зарегистрировать пользователя или отправить его вновь на форму регистрации, хотя, безусловно, это зависит от Вашей задачи.
Если Вы хотите научиться самостоятельно создавать подобные скрипты, то посмотрите мой Видеокурс «PHP и MySQL с Нуля до Гуру«: http://srs.myrusakov.ru/php
Копирование материалов разрешается только с указанием автора (Михаил Русаков) и индексируемой прямой ссылкой на сайт (http://myrusakov.ru)!
Добавляйтесь ко мне в друзья ВКонтакте: http://vk.com/myrusakov.
Если Вы хотите дать оценку мне и моей работе, то напишите её в моей группе: http://vk.com/rusakovmy.
Если Вы не хотите пропустить новые материалы на сайте,
то Вы можете подписаться на обновления: Подписаться на обновления
Если у Вас остались какие-либо вопросы, либо у Вас есть желание высказаться по поводу этой статьи, то Вы можете оставить свой комментарий внизу страницы.
Порекомендуйте эту статью друзьям:
Если Вам понравился сайт, то разместите ссылку на него (у себя на сайте, на форуме, в контакте):
Комментарии ( 61 ):
Эта капча очень слабая и можно легко написать скрипт который будет распозновать его. Михаил, советую поменять капчу при регистрации.
Капча является формальной, однако, какой смысл автоматической регистрации на моём сайте? У меня свой движок, своя система, поэтому никто не будет возиться с ним. Это никому не нужно, потому и капча чисто формальная, которая сделана максимально простой для обычных людей.
А зачем тогда капча вообще нужна?
Для защиты от авторегистраций. А вдруг кому-нибудь понадобится? Это Вам кажется, что капча очень лёгкая, уверяю, что разработать подобный алгоритм распознавания очень тяжело, поэтому человек передумает заниматься авторегистрацией на моём сайте.
Я немного усовершенствовал рисунок (сделал его меньше по высоте на 10 пикселей) и теперь нижние хвосты немного обрезаны. Такие, как «j» сканер определяет как «i», а «y» как «v», «p» как «o» или «D» ну и так далее. Просто нижняя часть скрыта настолько, что человек поймет, какая это буква, а fine reader нет 🙂
А я вобщем просто не заморачивался и скачал другой шрифт с корявыми буквами, в коде заменил verdana.tff на название моего шрифта и всё =)
Создание простой капчи на PHP
Статья, в которой разберём как написать простую Captcha на PHP. При этом рассмотрим как вариант с использованием сессии, так и куки.
Что такое Captcha?
Captcha (капча) – это некий тест, который человек решает очень легко, а робот – нет (научить компьютер решать его крайне сложно и затруднительно).
Используется Captcha на сайте для защиты от спама и повышенной нагрузки, которые создают роботы. Капчу можно очень часто встретить в формах регистрации, входа, отправки сообщений, при скачивании файлов и многих других местах.
В большинстве случаев капча отображается как некоторый искаженный или наложенный на фон текст, который посетителю сайта необходимо разобрать и ввести его в некоторое поле. Кроме текста на фоне используется и другие алгоритмы: найти среди множества картинок правильные, собрать пазл, переместить слайдер, нарисовать связь между несколькими картинками и т.д.
Исходные коды капчи
Исходные коды капчи расположены на GitHub: itchief/captcha.
Скриншот формы с капчей:
Процесс разработки капчи представлен в виде следующих этапов:
Верстка формы
Разработку Captcha начнём с создания формы. Для простоты форма будет состоять из капчи и кнопки отправить:
Генерация кода капчи и изображения
Формирование кода капчи и изображения выполним в файле «captcha.php», который поместим в папку «/assets/php»:
Если используете протокол HTTPS, то установите шестому аргументу значение true:
Для отправки капчи клиенту создается изображение, имеющее фон «bg.png», на котором с помощью функции imagefttext() пишется текст капчи.
Скрипт для обновления капчи на форме
Написание обработчика формы
Для обработки формы создадим файл «process-form.php» в папке «/assets/php/»
В этом файле будем сравнивать текст капчи, который пользователь ввел в форме с тем, который у нас хранится в сессии или куки.
В качестве результата будем возвращать JSON. В случае успеха:
По умолчанию этот файл сравнивает капчу со значением, находящимся в сессии. Если в «captcha.php» сохраняете капчу в куки, то здесь необходимо закомментировать секцию 1a и раскомментировать 1b:
Если используете протокол HTTPS, то замените шестой аргумент на значение true :
JavaScript для отправки формы на сервер через AJAX
Код для отправки формы на сервер через AJAX и обработки полученного результата:
Для отправки и получения cookie посредством fetch() установим:
Простые капчи с PHP и GD
К настоящему времени мы все столкнулись с изображениями с картинки в онлайн-формах. Капчи — неизбежное зло, и эта статья научит вас, как они сделаны.
Рисование капчи
Процедурный стиль, используемый в этой статье, присутствует только потому, что это является доказательством концепции и позволяет сохранить итоговый файл как можно более простым. В реальном проекте вы бы пошли ООП.
Показать пустое изображение
Изображение будет обрабатываться HTML, как если бы внешнее изображение отображалось с использованием тега «img». Используются две функции — одна для создания изображения и другая для отображения.
Первая строка указывает на начало сеанса пользователя на нашей странице.
Функция display () не имеет ничего, кроме обычного HTML-кода, который отображает изображение в браузере. Кроме этого, только стилизация делается для того, чтобы вывод выглядел презентабельно.
Внутри функции create_image() переменная используется для ссылки на изображение, возвращаемое функцией imagecreatetruecolor() которая принимает ширину и длину изображения в качестве аргументов. imagepng() создает изображение png с указанным именем и путем (в том же каталоге).
Черное изображение будет выводиться после нашего первого шага.
Обратите внимание, что функция imagepng() будет последней строкой нашей функции, и все последующие шаги должны быть вставлены в create_image() перед этим вызовом функции, иначе они не вступят в силу.
Создать форму
Предыдущее изображение будет белым после этого шага.
Генерация случайных линий.
Теперь мы фактически начинаем с того, что искажаем часть капчи. В PHP линии генерируются от начальной точки (x1, y1) до конечной точки (x2, y2). Теперь, когда мы хотим, чтобы наши линии касались обоих концов блока, мы будем сохранять координаты как то есть полную ширину нашего блока. Координаты будут генерироваться случайным образом. Это создаст только одну случайную строку. Мы сгенерируем несколько строк, поместив эту функцию в цикл for.
Функция imageline() принимает координаты x1, x2, y1, y2 в качестве аргументов в указанном порядке, кроме ссылки на изображение и цвета линии. Цвет линии был назначен так же, как и цвет фона на предыдущем шаге.
Генерация случайных точек.
Создать случайный текст
Когда помещено в цикл, это выглядит так
в следующем разделе.
Функция imagestring() записывает текст в наше изображение. У него есть 6 аргументов:
Вы также можете использовать функцию imagettftext() если вы хотите иметь больший шрифт и другой стиль шрифта. Требуется 2 дополнительных аргумента для угла и стиля шрифта текста.
Это сгенерирует текст из 6 букв алфавита. Мы всегда можем создать больше случайности, изменяя аспекты, которые были постоянными из-за простоты, такие как цвет, координаты y и т. Д.
Финальная капча будет выглядеть так
Текст, написанный на капче, будет меняться при каждом обновлении страницы.
Больше случайности может быть достигнуто путем создания дизайнов с пикселями или путем изменения цвета или размера.
Пользователи
Именно здесь принимается ответ пользователя, и после его обработки он / она получает ответ. Сначала создается простая форма с текстовым полем ввода и кнопкой отправки. Там может быть много способов обработки капчи в соответствии с требованиями сложных веб-приложений. Но для простоты этого примера мы будем обрабатывать его на той же странице.
Две строки, оставленные необъясненными в предыдущих фрагментах кода, теперь вступают в игру:
Мы изменим определение display() чтобы добавить структуру, похожую на форму.
Будут использоваться две кнопки отправки: одна для отправки строки, а другая для обновления страницы.
Следующие строки будут добавлены между двумя закрывающими тегами div (см. Комментарии в предыдущей функции display() )
Прежде чем двигаться дальше, мы должны знать, когда отображать, а когда не отображать поле ввода. Будет отображаться только
Чтобы достичь этого, мы заменим следующие строки нашего начального шага в начале статьи:
Обратите внимание, что функции create_image() и display() вызываются только в соответствии с двумя условиями, описанными выше.
Нам понадобится переменная сеанса с предыдущей страницы, поэтому сессия здесь не уничтожается. Сеанс будет автоматически уничтожен после закрытия окна браузера.
Капча будет выглядеть так
Если ввод неправильный, только тогда пользователю будет предложено снова.
Если ввод правильный, пользователю будет показано сообщение.
Существует небольшая оговорка — когда пользователь нажимает кнопку «Назад», любое изображение, уже имеющееся в кэше браузера, не будет перезагружаться, в то время как страница делает это. В POST-запросе кнопка «Назад» браузера покажет страницу «истек срок действия документа», но когда запрос GET, изображение не регенерируется.
Решение простое — каждый раз создавать уникальные имена изображений, чтобы браузер не находил их в кеше. Мы добавим уникальную строку, возвращенную нам встроенной функцией time() к имени изображения при создании и отображении в браузере.
Добавьте эту строку чуть ниже, где вы начали свою сессию:
Замените тег img src в функции display() на
В производственном приложении просто убедитесь, что вы изолировали папку, в которой хранятся изображения-капчи, иначе могут быть удалены и другие полезные изображения.
Вывод
Капча на PHP
Здравствуйте, уважаемые читатели блога LifeExample, сегодня я хочу выделить немного времени для ознакомления с нужным элементом для защиты сайта. Созданная, нами капча на PHP поможет вам защитить свой сайт от спама.
Перед тем как начать разработку капчи на PHP, давайте расставим все точки над i, и разберемся, откуда взялось это не понятное название и что оно означает.
Что такое капча
Сегодня задав, любому вебмастеру, вопрос: «Что такое капча?». Мы наверняка услышим: «Капча — это средство защиты от спам роботов». И в принципе это правильно, но давайте окунемся в историю, для того чтобы узнать более точный ответ на этот вопрос.
В начале 2000-х годов термин «КАПЧА», стал все чаще появляться на просторах всемирной паутины. Происхождение этого термина заслуга английского математика Алана Тюринга, который предложил в 1950 году эмпирический тест с целью определить сможет ли мыслить компьютер.
В те времена и по сей день, ученые и программисты многих университетов так и не создали искусственного интеллекта, эквивалентного человеческому разуму. Несмотря на это, труды Тюринга нашели отличное применение в полностью автоматизированном публичном тесте Тьюринга для различия компьютеров и людей (Completely Automated Public Turing test to tell Computers and Humans Apart ) сокращенно CAPCHA.
Теперь нам стало ясно, что слово КАПЧА – это лишь транскрипция аббревиатуры CAPCHA, скрывающей за собой длинную расшифровку.
Таким образом, отвечая на вопрос: «Что такое капча?», можно смело утверждать, что это тест для различия компьютеров и людей. А так как с помощью КАПЧИ мы можем точно определить, кто отправил ответ, человек или машина, то запросто применим это в своих целях.
Ну вот, я кажется удовлетворил свои писательские потребности, и могу приступить к созданию капчи на PHP.
Как сделать капчу
Если попросить яндекес или гугл, выдать нам ответ на данный вопрос, то можно встретить массу предлогаемых решений. Начав разбираться с алгоритмами работы, я прочитал много советов и примеров реализации капчи на PHP. Что позволило мне сделать определенные выводы, и реализовать скрипт таким образом чтобы он отвечал моим требованиям.
Мне необходимо было создать скрипт «Капча на PHP» требующий минимум усилий и отвечающий смыслу сей защиты.
Для создания примитивной, но отвечающей всем канонам защиты, нам потребуется иметь пять файлов:
Давайте по порядку, первое что мы хотим сделать это вывести картинку, для этого в файле index.php Пишем такие строки:
Тут стоит обратить внимание на указанный в атрибуте src, не характерный для него файл с расширением php. Все дело в том что файл captcha.php хоть и является скриптом, но возвращает ответ в виде изображения в формате png вполне подходящий для тега
img.
Взглянем на код скрипта генерирующиего картинку:
$letters = ‘ABCDEFGKIJKLMNOPQRSTUVWXYZ’ ; // алфавит
header ( ‘Content-type: image/png’ ) ; //тип возвращаемого содержимого (картинка в формате PNG)
Сама проверка как видите, тривиальна, но в реальности вместо этих сообщений, можно вставить необходимые алгоритмы, например для сохранения комментария, переданного вместе с проверочным текстом.
В результате у меня получился легковесный, и легко встраиваемый скрипт капчи на PHP
Читайте также похожие статьи:
Чтобы не пропустить публикацию следующей статьи подписывайтесь на рассылку по E-mail или RSS ленту блога.
Делаем капчу на PHP: установка reCAPTCHA и код с нуля
Всем привет! 🙂
Сегодня в продолжение разговора о том, что такое CAPTCHA и как заработать на капче, мы поговорим о том, как же её установить на свой сайт.
Сразу скажу, что для этого есть два пути: использовать существующие решения и разработать свою реализацию. Я решил рассмотреть оба варианта, чтобы вы сами могли выбрать тот, который вам по душе.
Поэтому сегодняшняя статья будет состоять из двух частей: установка reCAPTCHA от Google и того, как сделать капчу на PHP самостоятельно.
Указанные в статье примеры будут универсальные, без привязки к какой-либо платформе сайта, поэтому их можно использовать абсолютно на любом сайте, разработанном с использованием PHP и HTML.
Перед тем, как мы приступим к практике, немного теории о том, как работает капча, чтобы начинающим программистам и пользователям, не знакомым с программированием вообще, были понятны приведённые в статье действия по установке готовой и созданию капчи с нуля.
Если вы — опытный разработчик, то следующий абзац смело пропускайте.
Как работает капча
Если изучить внимательно существующие сайты, использующие капчу, то заметно, что она размещается на различных HTML формах ресурса, необходимых для осуществления пользовательских действий.
Механизм работы HTML форм следующий:
При использовании CAPTCHA на форме, она является одним из полей, значение которому указывает пользователь при решении капчи.
Затем на сервере проверяется значение капчи с правильным ответом и если они совпадают, то действие, производимое пользователем с помощью формы, выполняется.
Если же нет — выдаётся сообщение о неправильном вводе капчи, а иногда ещё и происходит фиксация IP-адреса, с которого была произведена попытка ввода неверной CAPTCHA, с дальнейшим внесением его в blacklist и блокированием доступа как к сайту в целом, так и к отдельным элементам.
На таком принципе была основана работа самых первых, так сказать, «классических» капч, и он до сих пор успешно применяется.
Разнообразие в данный механизм вносят JS капчи, которые отправляют AJAX запрос на сервер для проверки правильности ввода в режиме «реального времени», т.е. без перезагрузки страницы. Ярким представителем JavaScript капчи является всем известная Google reCAPTCHA noCAPTCHA, об установке которой мы поговорим далее.
Итак, как работает капча, мы разобрались. Из её принципа работы следует, что сама реализации капчи CAPTCHA будет содержать клиентский код (HTML элемента капчи) и серверный (PHP скрипт, обрабатывающий ответ пользователя).
В случае использования сторонних решений вам, скорее всего, понадобится только клиентский код. Серверный может быть ограничен только лишь отправкой запросов на сторонний сервер для проверки правильности ввода (у той же самой Google reCAPTCHA v2).
Делается это для того, чтобы не разглашать алгоритмы проверки, многие из которых могут быть запатентованными.
В случае реализации CAPTCHA с нуля серверная часть будет более масштабной, т.к. помимо самой проверки ввода капчи на сервере будет происходить генерация задания.
Теперь самое время перейти от сухой теории к практическому применению полученных знаний и сделать капчу на PHP самостоятельно.
Как сделать капчу на PHP — подготовка формы
Поскольку у меня на сайте капча уже установлена, то я решил не удалять её с целью демонстрации процесса повторной установки. Вместо этого я решил разработать примитивную HTML форму добавления комментариев на сайт, которая присутствует, наверное, на каждой современном ресурсе.
Она будет состоять из поля для ввода текста и кнопки «Отправить», между которыми в будущем мы будем размещать нашу капчу.
Код формы следующий:
Внешне она выглядит следующим образом:
Для удобства разработки и демонстрации результатов я решил создать новый репозиторий на Github, в котором можно будет найти весь код, приведённый в данной статье.
Для каждой реализации капчи создан отдельный каталог с идентичной структурой.
Поскольку наша форма комментариев на момент разработки является самостоятельным решением, а не частью существующей страницы сайта, то для её запуска в каждом каталоге есть файл index.php. В нём же происходит вызов файла form.html, содержащего описанный выше код.
Данная структура приложения была выбрана не случайно, т.к. она максимально соответствует реальным проектам, в которых html вызывается из PHP скрипта на сервере. Поэтому для интеграции кода капчи из статьи на свой сайт всё, что вам потребуется, — это скопировать form.html к себе на сервер, а код из index.php в свой серверный скрипт, вызывающий необходимую форму.
Или перенести содержимое вышеуказанных файлов в соответствующие.
Ну, а теперь приступаем к созданию капчи. Начнём с интеграции готовых сторонних решений, а далее я покажу, как сделать капчу на PHP своими руками.
Серверные скрипты были разработаны на PHP 5.6, но и на более поздних версиях (PHP 7+) с ними проблем не будет, т.к. я старался не использовать deprecated конструкции.
Установка reCAPTCHA
В качестве стороннего сервиса для установки капчи на сайт я решил использовать упоминавшуюся ранее Гугл рекапчу, которая на сегодняшний день является негласным стандартом CAPTCHA.
Поскольку данный сервис сторонний, то мы будет взаимодействовать с сервером reCAPTCHA посредством API. Если вы хоть раз использовали стороннюю АПИшку, то наверняка знаете, что доступ к ней возможен только с помощью специального ключа.
Для того, чтобы получить ключ reCAPTCHA, нужно создать Google-аккаунт, который даёт доступ ко всем сервисам данной компании (Youtube, Google диск, почта Gmail и др.) либо воспользоваться существующим (думаю, у большинства из вас он есть, если вы пользуетесь хотя бы одним из перечисленный сервисов).
После того, как вы залогинитесь в своём аккаунте, переходим на страницу https://www.google.com/recaptcha/admin, вводим название капчи (можно добавлять несколько CAPTCHA, поэтому имя нужно для банальной идентификации) и выбираем нужную версию reCAPTCHA.
Я лично рекомендую использовать вторую версию, которой является уже упоминавшаяся noCAPTCHA. Она как раз и является AJAX капчей, об особенностях которой мы также говорили. Первая версия рекапчи подойдёт любителям старой доброй графической капчи, для прохождения которой нужно вводить искажённые символы и цифры с картинок.
После выбора версии указываем доменные имена сайтов, на которых мы будем размещать PHP капчу, и выбираем галочку соглашения с условиями reCAPTCHA. В итоге должно было получиться следующее:
Нажимаем на кнопку «Регистрация» и попадаем на страницу управления созданной капчей с доступом к статистике её ввода, кодом reCAPTCHA и списком инструкций по установке reCAPTCHA на сайт.
Просто выполняем описанные шаги:
Добавление кода reCAPTCHA в виде поля на HTML форму описано достаточно подробно, поэтому не буду его ещё раз повторять. Просто выполните указанные выше инструкции.
В результате наша форма должна принять следующий вид:
Обратите внимание, что ваш сайт, на который вы добавляете reCAPTCHA, должен иметь доменное имя, указанное при её создании. Если оно будет отличаться от реального, использовать капчу не получится. Поэтому при настройке reCAPTCHA обязательно указывайте его корректно, даже в случае разработки на локальном веб-сервере.
Итак, HTML часть капчи завершена, настало время для серверной реализации. Как заметно из инструкции от Google, серверная проверка ввода капчи происходит следующим образом: после решения капчи пользователем результат отправляется на локальный сервер в виде значения параметра g-recaptcha-response.
Затем на локальном сервере нужно отправить POST-запрос на сервер reCAPTCHA, который уже и возвращает итоговый ответ: правильно ли была введена капча пользователем или он оказался роботом и не смог пройти все линии защиты.
Подробного примера реализации, как при установке reCAPTCHA на HTML форму, здесь у Google нет, т.к. неизвестно на каком языке написаны ваши серверные скрипты, а предоставлять примеры для всех существующих ныне серверных языков — это утомительно и долго, т.к. их около 20.
С целью упрощения жизни разработчиков существует масса библиотек для работы с reCAPTCHA, которые реализовывают АПИ для осуществления необходимых действий. PHP библиотека для работы с капчей предлагается даже самим Гуглом.
Но я не являюсь приверженцем их использования для таких простых действий, как банальная отправка запроса с одного сервера на другой, поэтому решил разработать PHP скрипт серверной реализации рекапчи самостоятельно.
Приведённый далее код можно найти в каталоге google_captcha публичного репозитория, ссылка на который была указана ранее.
Для отправки запроса на сервер Google для проверки правильности ввода PHP капчи был создан отдельный скрипт verify_captcha.php со следующим кодом:
Сперва в коде идёт проверка наличия параметра g-recaptcha-response в запросе, отправленном при подтверждении формы. Если же параметра нет, что равноценно отсутствию reCAPTCHA на форме, то скрипт завершает свою работу с соответствующим сообщением.
Далее мы отправляем POST запрос средствами PHP на сервер reCAPTCHA, как это требует Google, и анализируем полученный ответ, предварительно преобразовав его из JSON-формата в обычный объект.
Если ответ от сервера содержит параметр success со значением true, то всё прошло успешно. В противном случае ответ будет содержать параметр errors с указанием причины неудачного действия.
В итоге скрипт после завершения своей работы выводит на экран итоговое сообщение с текстом «Капча пройдена успешно!» в случае успешного выполнения серверного сценария и «Неверная капча!», если в процессе произошли какие-то ошибки.
При использовании приведённого примера интеграции Google reCAPTCHA в реальном проекте вместо сообщений должны быть прописаны необходимые действия.
Делаем капчу своими руками
Знаю, что я опоздал со своей статьёй, как минимум, лет на 10, когда капча только набирала обороты, практически каждый пытался написать капчу самостоятельно, и повсюду были примеры самописных реализаций.
Но тогда я ещё не занимался веб-программированием, поэтому алгоритмы работы капчи мне были неинтересны.
На данный момент готовых решений CAPTCHA существует великое множество, среди которых масса тщательно оттестированных и защищённых от всех существующих способов обхода реализаций.
Поэтому созданием самописок уже давно никто не занимается.
Но я всё же решил заняться собственной реализацией капчи, чтобы наконец разобраться с принципом её работы и познакомить вас с ним. Кроме того, мне была интересна реализация способов защиты от обхода капчи, с которыми я познакомил вас в предыдущей статье.
После того, как я замотивировался, осталось определиться с тем, на каком виде капчи остановиться, т.к. их существует великое множество.
Обычный чекбокс с надписью «Я не робот» или генерация математического примера показались мне слишком простыми в плане реализации, поэтому я решил остановиться на самом сложном — графической капче, для решения которой нужно правильно ввести символы, изображённые на картинке.
Выбрать я решил именно данный тип капчи ещё и потому, что для её реализации необходимы знания возможностей PHP для работы с изображениями, которые у меня слегка просели, т.к. на практике применяются крайне редко, и я всё уже позабывал.
Для генерации картинок на PHP уже, конечно же, существует масса готовых библиотек и решений. Из-за них, кстати, о функциях PHP для работы с изображениями мало кто в курсе, т.к. всем нужно всё делать побыстрее, для чего библиотеки как раз и создаются 🙂
В силу приведённых причин я и решил «изобрести очередной велосипед» для реализации графической капчи, кодом которого с вами и хочу поделиться. Он доступен в репозитории данного урока в каталоге image_captcha.
Вообще-то, слово «изобрести» в моём случае тоже не совсем подходит, т.к. за основу я взял существующую реализацию с Хабра — https://habrahabr.ru/post/120615/, структурировав её код, убрав некоторые ошибки, переделав непонравившиеся мне моменты и добавив свои наработки.
Так что далее в статье и в репозитории на github вы найдёте плоды коллективного труда и можете поучаствовать в его доработке и развитии сами, если сочтёте нужным.
HTML код элемента CAPTCHA для интеграции капчи на форму будет следующий:
Его нужно добавить в нужное место вашей HTML формы на сайте. В моём примере он будет располагаться после textarea name=»comment».
В файле captcha.php, мы будем создавать капчу, а на выходе выдавать изображение без сохранения его на диск. Во-первых, это сэкономит ресурсы сервера, а во-вторых, сократит время генерации капчи, что на больших проектах будет заметно.
Сперва я прописал генерацию символьной последовательности и самой картинки сплошным кодом, но потом решил его немного структурировать путём создания класса CaptchaValue с соответствующими методами. В итоге, captcha.php принял следующий вид:
При проектировании класса использовался интерфейс, содержащийся в файле CaptchaInterface.php, поэтому не забудьте добавить его на сервер, чтобы PHP не выдавал ошибки:
Файлы классов и интерфейса я вынес в отдельный каталог ‘classes’, который размещён на уровень ниже form.html и других файлов, расположенных в корне, поэтому либо сделайте как я, либо исправьте пути к файлам классов везде, где они подключаются в коде через PHP директиву include.
Сам класс CaptchaValue, код которого расположен в CaptchaValue.php, выглядит так:
Здесь без комментариев не обойтись, т.к. мы рассматриваем самый главный класс всего приложения.
Расскажу конкретно о каждом методе, начиная с самого главного, в котором происходит вся магия, — captcha_image().
Генерировать изображение капчи на PHP я решил следующим образом:
Теперь более подробно о функциях PHP для работы с изображениями, с помощью которых я реализовал задуманное.
За создание объекта изображения отвечает PHP функция imagecreatetruecolor(), которой я в качестве параметров передал размеры генерируемой картинки. В моём случае ширина изображения 150px и высотой 70px.
Сперва я попробовал использовать imagecreate(), но в данном варианте при каждой генерации изображения цвет фона принимал случайное значение, которое иногда плохо сочеталось с цветом символов, делая их нечитабельными. При использовании imagecreatetruecolor() цвет фона можно задавать.
Далее я указал толщину будущих наносимых линий с помощью imagesetthickness(), задав её 2 пикселя.
Для задания фона изображения я использовал PHP функцию imagefill(), в качестве аргумента которой был указан цвет, сгенерированный с помощью imagecolorallocate(). Цвет фона, как вы видите, динамический, т.е. каждый раз задаётся случайно.
Диапазоны цветовых каналов я подобрал таким образом, чтобы итоговый цвет был достаточно светлым, и символы капчи на нём были различимы.
Чтобы создать линии, которые будут под символами капчи, логично их нарисовать перед созданием самих символов. Поэтому это я и сделал с помощью функции PHP для рисования линий imageline(), у которой в качестве аргументов указаны координаты точек начала и конца каждой из них.
Значения также случайны, чтобы линии постоянно находились в различных местах. Так же случаен цвет каждой из них и их количество (в моём примере от 3 до 5 — больше делать не советую, т.к. будут ещё линии поверх символов).
Генерация самой случайной символьной последовательности происходит так:
Теперь вернёмся снова в image_captcha() к циклу прорисовки символов случайной строки:
Для прорисовки символов я решил воспользоваться различными шрифтами. Они должны быть в виде ttf файлов, и для них был создан отдельный каталог, путь к которому задаётся в виде private свойства класса CaptchaValue font_dir. Значение его задаётся в конструкторе.
Итак, сам цикл, где происходит перебор всей сгенерированной случайной строки, которую мы отрисовываем.
На следующей строке мы выбираем символ из строки, далее заново генерируем для него цвет и получаем идентификатор шрифта в массиве для получения доступа к нему.
Наносим символ на изображение с учётом всех полученных до этого данных PHP функцией imagettftext(), которая позволяет делать это с применением ttf шрифтов, что, отражает её название.
О назначении каждого её параметра можете прочитать в официальной документации PHP, я же хочу обратить внимание на третий, которому я указал значение rand(-10, 10).
Это — угол поворота символа. Если хотите, чтобы все были строго вертикальными, то укажите вместо моих данных 0, но не рекомендую, т.к. эта, с виду, простая мера способна усложнить жизнь хакерам и создаваемым ими ботам.
Рассмотрим оставшийся код метода captcha_image().
После нанесения строки на изображение, следуя алгоритму генерации капчи, следует нанесения шума на полученное промежуточное изображение. Я решил сделать это после прорисовки символов, т.к. он позволяет сделать в буквах своеобразные «дыры», что ещё больше усложнит распознавание капчи OCR.
Сперва мы генерируем число точек, которыми будем создавать шум (в моём случае их будет от 2000 до 4000, что для картинки 150х70 в самый раз).
Затем генерируем цвет каждой точки заново (без этого можно обойтись, задав всем одинаковый, например, белый) и наносим её на изображение с помощью стандартной PHP функции imagesetpixel().
После данного преобразования я ещё раз наношу линии уже поверх нарисованных символов описываемым ранее способом: в цикле по количеству линий с помощью функции PHP imageline(). Цвет каждой снова генерируется случайным образом.
Всё, картинка готова.
Осталось только вывести её на экран в окне браузера с помощью PHP функции imagepng(), для чего браузеру передаются соответствующие заголовки с помощью PHP header(), и очистить память сервера от изображения, которое мы генерировали, с помощью PHP imagedestroy().
В итоге, у нас получилось сделать капчу, которая выглядит следующим образом:
Для ещё большей защиты от взлома я решил добавить в данную реализацию генерируемое название поля для ввода значения капчи, чтобы хакерам было сложнее вводить её автоматически.
За генерацию отвечает класс CaptchaField, описанный в скрипте classes/CaptchaField.php, а именно его метод generate_code(), который вызывается в главном файле, запускающем всю реализацию как самостоятельный сайт, index.php:
Сам класс CaptchaField выглядит следующим образом:
Прежде всего я отключил сообщения об ошибках типа warning, notice и прочих, с которыми скрипт будет работать, но они будут присутствовать в выводе результатов, т.е. в имени поля капчи мы их увидим, что совсем не нужно.
Поскольку данный класс реализует интерфейс CaptchaInterface, то должен переопределять его методы generate_code() и session_write().
В данном классе, как и в случае CaptchaValue, они отвечают за генерацию кода и запись его в сессию, соответственно. Только код в данной ситуации у нас другой.
Для генерации имени поля для ввода капчи я решил использовать PHP функцию uniqid для генерации случайного идентификатора. Первый параметр функции пустой, т.к. я решил обойтись без строчного префикса, а второй — true, что добавляет энтропию для увеличения уникальности значения и удлиняя его до 23 символов вместо 13.
Ну, и для большей секьюрности я решил ещё дополнительно применить двойное md5 шифрование. В результате, метод generate_code() класса CaptchaField вернёт следующее значение, предварительно записав его в переменную сессии captcha_field:
Итак, сама PHP CAPTCHA и сгенерированное имя поля для её ввода готовы.
Теперь осталось только рассмотреть код, который отвечает за проверку введённого пользователем значения капчи с тем, что было ему предложено.
За проверку, как и в случае реализации Google noCAPTCHA reCAPTCHA, которая была приведена выше, отвечает серверный скрипт verify_captcha.php.
Поскольку я решил структурировать данную реализацию путём создания классов, то verify_captcha.php выглядит так:
Сам же класс CaptchaVerify выглядит следующим образом:
Главным его методом является verify_code(), который и вызывается в verify_captcha.php.
В нём сперва происходит чтение данных из сессии (сгенерированного значения капчи и поля для её ввода, а также время генерации картинки CAPTCHA на сервере), а затем происходят проверки на содержание в сессии соответствующих значений и наличие среди параметров запроса имени submit кнопки формы, что свидетельствует о том, что пользователь вводил код через форму вручную, а не программно.
Далее мы вычисляем время, потраченное пользователем на ввод капчи на основании текущего времени в момент проверки введённого значения и времени генерации капчи. Если оно меньше 6 секунд, то с большой вероятностью капчу вводили программно без соблюдения таймаутов.
Поэтому в таком случае скрипт завершается с соответствующим сообщением об ошибке «Вы или робот или вводите капчу слишком быстро!». Кстати, данный текст подскажет реальным пользователям, которые вводят PHP CAPTCHA слишком быстро, делать это медленее, чтобы их старания были засчитаны.
Ну, а затем мы проверяем введённое значение капчи из запроса с тем, которое было сгенерировано изначально и записано в сессию. Поскольку перед записью в сессию значение шифровалось, то мы то же самое делаем и со значением пользователя, после чего сравниваем их.
Если они совпадают, то капча введена успешно, о чём сообщает соответствующий месседж (вместо него у вас должно выполняться ваше реальное действие, которое защищалось с помощью капчи).
Во всех остальных случаях выдаются сообщения об ошибке с соответствующими текстами с помощью функции error_msg(), которая помимо завершения выполнения скрипта ещё и фиксирует в сессии попытку неверного ввода по IP клиента.
Если таковых наберётся больше 10, то выполнения действия невозможно будет даже при правильном вводе капчи. Для разблокировки нужно будет написать администратору, чтобы тот сбросил счётчик.
Данную цифру лучше, конечно, хранить в БД, а не в сессии, т.к. последняя имеет ограниченный срок жизни и спустя некоторое время данная блокировка перестанет работать.
Поэтому на практике используйте вариант с БД. В сессию запись была сделана в качестве демонстрации данной возможности.
Или вообще можете отказаться от данного способа защиты капчи от взлома, если считаете его слишком жёстким. Всё в ваших руках 🙂
Для этого я, собственно говоря и описал весь код подробно, чтобы даже люди, не знакомые с программированием, смогли бы его настроить под свои нужды.
Надеюсь, я ответил на вопрос о том, как сделать капчу на PHP. Причём поделился с вами аж двумя вариантами.
Честно скажу, что реализованная мною графическая капча не является бронебойной и 100% защиту от всех современных способов взлома не предоставляет. Повторюсь, мне была интересная её реализация только с точки зрения практического применения способов защиты от обхода капчи и хотелось вспомнить возможности PHP для работы с изображениями.
Своей цели я достиг. А если ещё и смог быть вам полезным своим трудом — для меня будет вдвойне приятно 🙂
Если вы планируете устанавливать капчу на реальный проект, то рекомендую воспользоваться всё-таки готовыми и оттестированными решениями. Той же самой Google reCAPTCHA, порядок установки которой описан в первой части статьи.
Мой код будет полезен больше таким же разработчикам, каковым я сам являюсь. Кстати, надеюсь на вашу помощь при тестировании приведённого кода и ценные замечания по поводу его недостатков, которые вполне могут присутствовать.
Поэтому пишите свои отзывы в комментариях под статьёй: что понравилось, что не понравилось, что можно улучшить.
Очень надеюсь на вашу помощь и поддержку.
P.S.: если вам нужен сайт либо необходимо внести правки на существующий, но для этого нет времени и желания, могу предложить свои услуги.
Более 5 лет опыта профессиональной разработки сайтов. Работа с PHP, OpenCart, WordPress, Laravel, Yii, MySQL, PostgreSQL, JavaScript, React, Angular и другими технологиями web-разработки.
Опыт разработки проектов различного уровня: лендинги, корпоративные сайты, Интернет-магазины, CRM, порталы. В том числе поддержка и разработка HighLoad проектов. Присылайте ваши заявки на email cccpblogcom@gmail.com.
И с друзьями не забудьте поделиться 😉