Мы все с вами привыкли видеть на сайтах при заполнении любой формы трудночитаемую картинку с рандомными символами и цифрами. Данная картинка называется КАПТЧА (от CAPTCHA — англ. C ompletely A utomated P ublic T uring test to tell C omputers and H umans A part — полностью автоматизированный публичный тест Тьюринга для различения компьютеров и людей). Как описано в расшифровке аббревиатуры данная картинка позволяет определить робот или человек заполняет форму.
В настоящее время существует множество разновидностей КАПТЧ, это может быть картинка с рандомным текстом, или картинка с математическими действиями, блок картинок в которых нужно выбрать определенные предметы и т.д. Все эти картинки направлены на борьбу с роботами спамерами, которые заполняют формы автоматически.
Стоит понимать что КАПЧА это не панацея, и при желании ее всегда можно распознать автоматически использую соответствующие сервисы. Данная проблема актуальна для высоконагруженных веб сайтов с большой аудиторией, например социальные сети или популярные доски объявлений такие как Авито и т.д.
Переходя от вступления к практики, для написания КАПТЧИ нам понадобится библиотека GD. GD Graphics Library (GD) — программная библиотека, написанная Томасом Баутелом ( Thomas Boutell ) и другими разработчиками для динамической работы с изображениями. Данная библиотека работает с множеством других языков программирования и служит для работы с графикой. Как вы уже догадались, мы будем с помощью библиотеки GD и PHP создавать свою картинку с рандомным текстом. Graphics Library позволяет также редактировать существующие изображения, а именно наложение логотипа на картинку, изменения размеров загружаемого изображения и многое другое.
Список функция для работы с графикой в PHP
- gd_info — Вывод информации о текущей установленной GD библиотеке
- getimagesize — Получение размера изображения
- getimagesizefromstring — Получение размера изображения из строки данных
- image_type_to_extension — Получение расширения файла для типа изображения
- image_type_to_mime_type — Получение Mime-типа для типа изображения, возвращаемого функциями getimagesize, exif_read_data, exif_thumbnail, exif_imagetype
- image2wbmp — Выводит изображение в браузер или пишет в файл
- imageaffine — Return an image containing the affine transformed src image, using an optional clipping area
- imageaffinematrixconcat — Concatenate two affine transformation matrices
- imageaffinematrixget — Get an affine transformation matrix
- imagealphablending — Задание режима сопряжения цветов для изображения
- imageantialias — Требуется ли применять функции сглаживания или нет
- imagearc — Рисование дуги
- imagechar — Рисование символа по горизонтали
- imagecharup — Рисование символа вертикально
- imagecolorallocate — Создание цвета для изображения
- imagecolorallocatealpha — Создание цвета для изображения
- imagecolorat — Получение индекса цвета пиксела
- imagecolorclosest — Получение индекса цвета ближайшего к заданному
- imagecolorclosestalpha — Получение индекса цвета ближайшего к заданному с учетом прозрачности
- imagecolorclosesthwb — Получение индекса цвета, имеющего заданный тон, белизну и затемнение
- imagecolordeallocate — Разрыв ассоциации переменной с цветом для заданного изображения
- imagecolorexact — Получение индекса заданного цвета
- imagecolorexactalpha — Получение индекса заданного цвета и альфа компонента
- imagecolormatch — Делает цвета палитровой версии изображения более соответствующими truecolor версии
- imagecolorresolve — Получает идентификатор конкретного цвета или его ближайший аналог
- imagecolorresolvealpha — Получает идентификатор конкретного цвета и альфа компонента или его ближайший аналог
- imagecolorset — Установка набора цветов для заданного индекса палитры
- imagecolorsforindex — Получение цветов, соответствующих индексу
- imagecolorstotal — Определение количества цветов в палитре изображения
- imagecolortransparent — Определяет цвет как прозрачный
- imageconvolution — Наложение искривляющей матрицы 3х3, используя коэффициент и смещение
- imagecopy — Копирование части изображения
- imagecopymerge — Копирует часть изображения с наложением
- imagecopymergegray — Копирует часть изображения с наложением в градациях серого
- imagecopyresampled — Копирование и изменение размера изображения с ресемплированием
- imagecopyresized — Копирование и изменение размера части изображения
- imagecreate — Создание нового палитрового изображения
- imagecreatefromgd2 — Создание нового изображения на основе GD2 или URL
- imagecreatefromgd2part — Создание нового изображения на основе части GD2 файла или URL
- imagecreatefromgd — Создание нового изображения на основе GD файла или URL
- imagecreatefromgif — Создает новое изображение из файла или URL
- imagecreatefromjpeg — Создает новое изображение из файла или URL
- imagecreatefrompng — Создает новое изображение из файла или URL
- imagecreatefromstring — Создание нового изображения из потока представленного строкой
- imagecreatefromwbmp — Создает новое изображение из файла или URL
- imagecreatefromwebp — Создает новое изображение из файла или URL
- imagecreatefromxbm — Создает новое изображение из файла или URL
- imagecreatefromxpm — Создает новое изображение из файла или URL
- imagecreatetruecolor — Создание нового полноцветного изображения
- imagecrop — Crop an image using the given coordinates and size, x, y, width and height
- imagecropauto — Crop an image automatically using one of the available modes
- imagedashedline — Рисование пунктирной линии
- imagedestroy — Уничтожение изображения
- imageellipse — Рисование эллипса
- imagefill — Заливка
- imagefilledarc — Рисование и заливка дуги
- imagefilledellipse — Рисование закрашенного эллипса
- imagefilledpolygon — Рисование закрашенного многоугольника
- imagefilledrectangle — Рисование закрашенного прямоугольника
- imagefilltoborder — Заливка цветом
- imagefilter — Применяет фильтр к изображению
- imageflip — Flips an image using a given mode
- imagefontheight — Получение высоты шрифта
- imagefontwidth — Получение ширины шрифта
- imageftbbox — Определение границ текста выводимого шрифтом freetype2
- imagefttext — Нанесение текста на изображение, используя шрифты FreeType 2
- imagegammacorrect — Применение гамма коррекции к GD изображению
- imagegd2 — Вывод GD2 изображения в браузер или файл
- imagegd — Вывод GD-изображения в браузер или в файл
- imagegetclip — Get the clipping rectangle
- imagegif — Выводит изображение в браузер или пишет в файл
- imagegrabscreen — Захватывает изображение с экрана
- imagegrabwindow — Захватывает изображение окна
- imageinterlace — Включение или выключение интерлейсинга
- imageistruecolor — Определяет, является ли изображение полноцветным
- imagejpeg — Выводит изображение в браузер или пишет в файл
- imagelayereffect — Установка флага альфа сопряжения для использования эффектов наложения изображений
- imageline — Рисование линии
- imageloadfont — Загрузка шрифта
- imagepalettecopy — Копирование палитры из одного изображения в другое
- imagepalettetotruecolor — Converts a palette based image to true color
- imagepng — Вывод PNG изображения в браузер или файл
- imagepolygon — Рисование многоугольника
- imagepsbbox — Выдает параметры рамки, обрамляющей текст написанный шрифтом PostScript Type1
- imagepsencodefont — Изменение вектора кодировки шрифта
- imagepsextendfont — Растягивание или сжатие шрифта
- imagepsfreefont — Освобождение памяти, занятой шрифтом PostScript Type
- imagepsloadfont — Загрузка шрифта PostScript Type 1 из файла
- imagepsslantfont — Наклон шрифта
- imagepstext — Рисование текста поверх изображения, используя шрифты PostScript Type1
- imagerectangle — Рисование прямоугольника
- imagerotate — Поворот изображения с заданным углом
- imagesavealpha — Установка флага сохранения всей информации альфа компонента (в противовес одноцветной прозрачности) и сохранение PNG изобаржения
- imagescale — Scale an image using the given new width and height
- imagesetbrush — Установка изображения (кисти), посредством которого будут рисоваться линии
- imagesetclip — Set the clipping rectangle
- imagesetinterpolation — Set the interpolation method
- imagesetpixel — Рисование точки
- imagesetstyle — Установка стиля рисования линий
- imagesetthickness — Установка толщины линий
- imagesettile — Установка изображения, которое будет использовано в качестве элемента мозаичной заливки
- imagestring — Рисование строки текста горизонтально
- imagestringup — Рисование строки текста вертикально
- imagesx — Получение ширины изображения
- imagesy — Получение высоты изображения
- imagetruecolortopalette — Преобразование полноцветного изображения в палитровое
- imagettfbbox — Получение параметров рамки обрамляющей текст написанный TrueType шрифтом
- imagettftext — Рисование текста на изображении шрифтом TrueType
- imagetypes — Возвращает список типов изображений, поддерживаемых PHP сборкой
- imagewbmp — Выводит изображение в браузер или пишет в файл
- imagewebp — Output a WebP image to browser or file
- imagexbm — Вывод XBM изображения в браузер или файл
- iptcembed — Встраивание двоичных IPTC данных в JPEG изображение
- iptcparse — Разбор двоичных IPTC данных на отдельные тэги
- jpeg2wbmp — Конвертирует изображение из формата JPEG в WBMP
- png2wbmp — Преобразование PNG файла в WBMP
Приступаем к написанию КАПТЧИ. Первое что нам нужно – это генератор случайных чисел. Такой генератор я писал в одной из статей Генератор пароля + соль в пароле для хранения в MySQL . Так же необходимо загрузить файл шрифта на сервер для использования его в КАПТЧе.
<?php
/**
* КАПТЧА 1.0
* Site: https://bezramok-tlt.ru
* Создание КАПТЧИ своими руками
* Autor: Админ
*/
//Запускаем сессию
session_start();
//Устанавливаем кодировку и вывод всех ошибок
header('Content-Type: text/html; charset=UTF-8');
error_reporting(E_ALL);
function getRandString($num)
{
//Генерим массив из букв
$letter = range('a', 'z');
//Генерим массив из цифр
$number = range(0, 9);
//Создаем строку с маленькими и большими буквами и цифрами
$letter = implode('',$letter);
$letter = $letter.strtoupper($letter).implode('',$number);
//Строка с генерированым кодом
$randStr = '';
for ($i = 0; $i < $num; $i++){
//Прогоняем циклом столько, сколько нужно символов в строке
$randStr .= $letter[rand(0, strlen($letter) - 1)];
}
return $randStr;
}
//Функция генерации цвета
function randColor($imgPng, $red = null, $green = null, $blue = null)
{
if(is_numeric($red) and is_numeric($green) and is_numeric($blue))
return imagecolorallocate($imgPng, $red, $green, $blue);
else
return imagecolorallocate($imgPng, rand(0, 255), rand(0, 255),rand(0, 255));
}
//Путь до нужного шрифта
$fonts = "./font/verdana.ttf";
//Нижняя плашка каптчи
$url = "http://bezramok-tlt.ru";
//Размер шрифта каптчи
$fontSize = 24;
$fontSizeUrl = 12;
//Размеры холста холста
$width = 200;
$height = 80;
//Количество линий и пикселей на холсте
$countLine = rand(0, 10);
$countPixel = rand(200, 1000);
// Сколько символов будем выводить на картинке
$numbers = 5;
//Получаем сгенерированую строку
$randStr = getRandString($numbers);
// Записываем каптчу в сессию
$_SESSION['captcha'] = $randStr;
// Создаем картинку (холст) размером 200 X 60
$imgPng = imagecreatetruecolor($width, $height);
// Создаем фон холста, RGB(255, 181, 181)
$imgColor = randColor($imgPng, 255, 181, 181);
//Зададим цвет линиям, у меня он динамический
$lineСolor = randColor($imgPng);
//Зададим цвет для точек, у меня он динамический
$pixelСolor = randColor($imgPng);
//Цвет текста, у меня он динамический
$textColor = randColor($imgPng);
//Цвет полоски с текстом в низу картинки
$bgColor = randColor($imgPng, 0, 0, 0);
//Цвет текста URL красный
$redColor = randColor($imgPng, 255, 0, 0);
//Определяем фон картинки
imagefilledrectangle($imgPng, 0, 0, $width, $height, $imgColor);
//Создаем линии на холсте
for ($i = 0; $i < $countLine; $i++) {
imageline($imgPng, 0, rand(0, $height), $width, rand(0, $height), $lineСolor);
}
//Создаем точки на холсте
for ($i = 0; $i < $countPixel; $i++) {
imagesetpixel($imgPng, rand(0, $width) , rand(0, $height), $pixelСolor);
}
//Пишем по букве не холсте
for ($i = 0; $i < strlen($randStr); $i++)
{
//Растояние между символами
$x = ($width - 20) / strlen($randStr) * $i + 10;
//Случайное смещение
$x = rand($x, $x + 4);
//Координата Y
$y = $height - (($height - $fontSize) / 2 );
//Случайны цвет отдельного символа
$letterColor = randColor($imgPng);
//Случайный угол наклона символов
$angle = rand(-25, 50);
//Пишем текст на холсте (наш код каптчи)
imagettftext($imgPng, $fontSize, $angle, $x, $y, $letterColor, $fonts, $randStr[$i]);
}
// создаем рамку для текста
$bbox = imagettfbbox($fontSizeUrl, 0, $fonts, $url);
//Высчитываем координаты для выравнивания по центру
$textX = $bbox[0] + (imagesx($imgPng) / 2) - ($bbox[4] / 2);
//Определяем фон картинки
imagefilledrectangle($imgPng, 0, 60, $width, $height, $bgColor);
//Надпись с URL
imagettftext($imgPng, $fontSizeUrl, 0, $textX, 75, $redColor, $fonts, $url);
// Посылаем заголовок серверу о том что у нас картинка в формате png
header("Content-type: image/png");
imagepng($imgPng);
//Освобождаем
imagedestroy($imgPng);
?>
Результат работы скрипта
Если обратиться к этому файлу через браузер, то мы получим вот такую картинку.
<!DOCTYPE html>
<html lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<meta charset="UTF-8">
<!-- Latest compiled and minified CSS -->
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous">
<title>Document</title>
</head>
<body>
<div class="container">
<div class="row">
<div class="col-md-6 col-md-offset-3">
<h1 class="text-center">Форма работы каптчи:</h1>
<!-- Выводим ошибки -->
<?php
if(count($err) > 0)
echo '<div class="alert alert-danger">'. implode('<br>', $err).'</div>';
if(!empty($ok))
echo '<div class="alert alert-success">'. $ok .'</div>';
?>
<form method="POST" action="">
<div class="form-group">
<label for="exampleInputEmail1">Email</label>
<input type="email" class="form-control" id="exampleInputEmail1" name="email" placeholder="Email">
</div>
<div class="form-group">
<label for="code">Код с картинки</label>
<input type="text" class="form-control" id="code" name="captcha" placeholder="Код с картинки">
</div>
<div class="form-group">
<p class="help-block"><img id="captcha" src="captcha.php" alt=""> <button class="btn btn-default" id="refreshImg"><span class="glyphicon glyphicon-refresh" aria-hidden="true"></span></button></p>
</div>
<button type="submit" class="btn btn-primary" name="send">Отправить</button>
</form>
</div>
</div>
</div>
<script src="http://code.jquery.com/jquery-2.2.4.min.js" integrity="sha256-BbhdlvQf/xTY9gja0Dq3HiwQF8LaCRTXxZKRutelT44=" crossorigin="anonymous"></script>
<script>
$(document).ready(function(){
$('#refreshImg').click(function(e){
e.preventDefault();
$('#captcha').attr('src', 'captcha.php?r=' + Math.random());
})
});
</script>
</body>
</html>
<?php
/**
* Главный файл
* Site: http://bezramok-tlt.ru
* Создание КАПТЧИ своими руками
*/
//Запускаем сессию
session_start();
//Устанавливаем кодировку и вывод всех ошибок
header('Content-Type: text/html; charset=UTF8');
error_reporting(E_ALL);
//Инициализируем переменные для работы
$err = array();
//Если нажата кнопка отправки формы
if(isset($_POST['send'])){
//Утюжим пересенные
if(!filter_var($_POST['email'], FILTER_VALIDATE_EMAIL))
$err[] = 'Не верный email!';
if($_SESSION['captcha'] != $_POST['captcha'])
$err[] = 'Код с картинки не совпадает!';
if(empty($err))
$ok = 'Вы прошли проверку!';
}
//Подключаем наш шаблон
include './form.html';
?>
14/03/2017 23:57:06
10/03/2017 11:04:41