Фев
Как сделать капчу (captcha) php для сайта


Для защиты сайта от регистрации ботов используют так называемый тест Тьюринга. В простонародии он называется капча (CAPTCHA). Я решил сделать капчу (captcha) используя php. Об этом и пойдёт разговор в этой заметке.
Что же по сути такое тест Тьюринга. А это проверка, является ли пользователь живым человеком или ботом. Устанавливается задача, которую человек решит легко, а для программного решения потребуется очень много ресурсов. Обычно задачей является распознавание текста на картинке. Для усложнения распознования картинки с помощью компьютера добавляют к изображению дополнительные линии и шумы. Исходя из выше изложенной информации, напрашивается вывод, что мы должны научиться генерировать изображения с помощью php. Для работы с графикой в php существует библиотека GD2. Давайте сначала её подключим и разберёмся как с её помощью сделать captcha для сайта.
Подключение библиотеки GD2 к PHP
Находим в папке: C:\Program Files\PHP\ext файл php_gd2.dll(это и есть библиотека), и копируем в c:\windows. В файле
c:\windows\php.ini находим строку extension=php_gd2.dll
и раскоментируем. Не забываем перезапустить apache. У меня веб сервер apache стоит на windows. Здесь заметка как я его ставил.
Так что процесс установки GD2 может у вас отличаться от моего. Теперь давайте разберём основные функции GD2.
Функции библиотеки GD2 PHP
Создание и генерация изображения
| Функция | Что функция делает |
|---|---|
$myimg = imageCreate(500, 300) |
Делаем изображение (256 цветов) |
$myimg = imageCreateTrueColor(500, 300) |
Делаем изображение (17 млн. цветов) |
header("Content-type: image/jpeg");
imageJpeg($myimg[,"filename"][,quality]) |
Создание JPEG-картинки |
header("Content-type: image/gif");
imageGif ($myimg[,"filename"]);
|
Создание GIF-картинки |
header("Content-type: image/png");
imagePng($myimg[,"filename"]);
|
Создание PNG-картинки |
Рисование
| Функция | Что функция делает |
|---|---|
imageAntiAlias($myimg, true) |
Сглаживание (antialiasing) |
$mycolor = imageColorAllocate($myimg, 255, 0, 0) |
Определение цвета |
imageLine($myimg, 25, 25, 70, 290, $mycolor);
|
Рисуем линии, цифры это координаты точек |
imageRectangle($myimg, 25, 25, 70, 290, $mycolor);
|
Рисуем прямоугольник, цифры это координаты углов |
imageFilledRectangle
($myimg, 20, 20, 65, 295, $mycolor);
|
Заливка фона |
$points = array(0,0,110,210,310,210);
imagePolygon($myimg, $mypoints, 3, $mycolor);
imageFilledPolygon
($myimg, $mypoints, 3, $mycolor); |
Рисуем многоугольник |
imageEllipse
($myimage, 200, 150, 300, 200, $color); |
Рисуем эллипс. Первые 2е цифры координаты центра эллипса, 2е 2е высота и ширина эллипса (x, y) |
imageString
($myimage, 3, 130, 350, "Hai", $mycolor); |
Рисуем строку текста. 1я цифра размер шрифта ( max 5) |
imageTtfText
($myimg, 30, 10, 310, 160, $mycolor,
"my.ttf", "Hai"); |
Рисуем строку текста. Применяем TrueType-шрифты. 1я цифра размер шрифта, 2я угол наклона, 3-4 координаты бокса, шрифт, текст |
$myimg = imageCreateFromJPEG("myimage.jpg");
$myimg = imageCreateFromGIF("myimage.gif");
$myimg = imageCreateFromPNG("myimage.png");
|
Делаем новое изображения на базе имеющегося |
Создание капчи (captcha) php
Теперь мы обладаем нужной информацией для создания капчи (captcha) php. Я написал свой небольшой класс, который генерирует картинку капчи. Файл с классом
называется mycaptcha.php. Листинг ниже.
<?php
class mycaptcha{
//сюда получаем сгенерированную капчу
public $keycaptcha;
function captcha(){
//создаём картинку
$myimg = imageCreateTrueColor(250, 50);
//количество символов
$nChars=5;
//генерируем captcha
$randStr=substr(md5(uniqid()),0,$nChars);
$this->keycaptcha=$randStr;
//задаём подложку из картинки
$myimg = imageCreateFromJPEG("noise.jpg");
imageAntiAlias($img, true);
//генерируется случайное число от 1 до 4
function getColor(){
$x=rand(1,4);
return $x;
}
//координата символа по гориз.
$j=20;
for ($i = 0; $i < 5; $i++) {
//получаем $i символ из сгенерир.
$z=substr($randStr, $i, 1);
//рандомно получаем размер символа
$size=rand(25,30);
//рандомно получаем угол поворота символа
$angle=-30+rand(0,60);
//получаем рандомно цвет символа
$n=getColor();
switch ($n) {
case 1: $c=imageColorAllocate($myimg, 255, 0, 0); break;
case 2: $c=imageColorAllocate($myimg, 0, 200, 0); break;
case 3: $c=imageColorAllocate($myimg, 0, 0, 255); break;
case 4: $c=imageColorAllocate($myimg, 0, 0, 0); break;
}
//генерируем картинку
imageTtfText($myimg, $size, $angle, $j, 30, $c,"bellb.ttf", "$z");
$j+=35;
}
//выводим captcha
header("Content-type: image/jpeg");
imageJpeg($myimg);
}
function getKeycaptcha(){
return $this->keycaptcha;
}
}
?>
Теперь нам этот класс нам нужно подключить в файл, который будет генерировать captcha php. Файл я назвал imgcaptcha.php. Листинг:
<?php
//запускаем сессию
session_start();
//подключаем класс
include('mycaptcha.php');
//вызываем класс
$captcha = new mycaptcha();
//генерим капчу
$captcha->captcha();
//записываем значение капчи в сессию
$_SESSION['keycaptcha'] = $captcha->getKeycaptcha();
?>
Сессия нам нужна для того что бы передать значение капчи в другой файл на проверку.
Теперь нам осталось подключить captcha php на сайт. Для этого надо создать файл, где мы будем выводить капчу и проверять правильность её введения. Назовём этот файл index.php. Листинг ниже.
<?php
header("Content-Type: text/html; charset=utf-8");
//запустим сессию
session_start();
//создадим переменную
$result="";
/*ф-я фильтрации*/
function myclear($dt){
$dt=stripslashes($dt);
$dt=strip_tags($dt);
$dt=trim($dt);
return $dt;
}
//проверим была ли отправлена форма
if($_SERVER["REQUEST_METHOD"]=="POST"){
//проверка существования сессионной переменной
//браузер запрашивает картинку, если графика
//отключена переменной не существует
if (isset($_SESSION['keycaptcha'])){
//если капча введена правильно
if($_SESSION['captcha_keystring']==myclear($_POST["str"])){
$result="Капча введена верно.";
}else{
$result="Капча введена неверно!!! Вы ввели: "
.myclear($_POST["str"])."Капча была: "
.$_SESSION['keycaptcha'];
}
}else{
$result="ВКЛЮЧИ ГРАФИКУ!";
}
}
?>
<img src="/imgcaptcha.php" id="captcha">
<button type="button" onclick="document.getElementById('captcha').src =
'imgcaptcha.php?' + Math.random()"</button>
<form action="" method="post">
<input type="text" name="str" placeholder="Введите капчу">
<button type="submit" >Отправить</button>
</form>
<?php
//вывод сообщения
echo $result;
//очищаем сессию
unset($_SESSION['keycaptcha']);
?>
Разберёмся что происходит в index.php. Мы выводим капчу, выведя imgcaptcha.php как картинку. В форму мы вводим значение капчи и отсылаем его методом post
самим себе. Так же получаем значение капчи из сессии. Это значение, которое сгенерировалось классом и вывелось в виде картинки. Сравниваем значение капчи
введённое в поле и полученное из сессии. В зависимости от проверки выводим сообщение. Обращу ваше внимание на такую вот конструкцию js
onclick="document.getElementById('captcha').src =
'imgcaptcha.php?' + Math.random(). При клике по кнопке происходит перезагрузка картинки капчи. Что бы изображение не кешировалось к адресу картинки
imgcaptcha.php добавляется случайное число с помощью Math.random(). Ну на этом я думаю всё, тема капчи php раскрыта. Я думаю уже не
должно возникать вопросов как сделать капчу (captcha) php для сайта. Если есть вопросы, задавайте их в комментариях.
Комментарии
Николай
19.02.2017 18:51 Ответить
Хорошая, интересная, полезная статья!
Виктор
15.09.2017 11:24 Ответить
Класс капчи сделан криво. Без конструктора создается две капчи, и в сессию пишется первая. Соответственно проверка не работает
Виктор
15.09.2017 11:28 Ответить
class captcha{
public $keycaptcha;
private function getColor(){
$x=rand(1,4);
return $x;
}
public function __construct(){}
public function captcha(){
$myimg = imageCreateTrue Color(250, 50);
$nChars=5;
$randStr=substr (md5(uniqid()), 0,$nChars);
$this->keycaptc ha=$randStr;
$myimg = imageCreateFrom JPEG("../../img /noise.jpg");
imageAntiAlias( $myimg, true);
$j=20;
Виктор
15.09.2017 13:14 Ответить
for ($i = 0; $i < 5; $i++) {
$z=substr($rand Str, $i, 1);
$size=rand(25,3 0);
$angle=-30+rand (0,60);
$n=$this->getCo lor();
switch ($n) {
case 1: $c=imageColorAl locate($myimg, 255, 0, 0); break;
case 2: $c=imageColorAl locate($myimg, 0, 200, 0); break;
case 3: $c=imageColorAl locate($myimg, 0, 0, 255); break;
case 4: $c=imageColorAl locate($myimg, 0, 0, 0); break;
}
imageTtfText($m yimg, $size, $angle, $j, 30, $c,"../../fonts /bellb.ttf", "$z");
$j+=35;
}
header("Content -type: image/jpeg");
imageJpeg($myim g);
imagedestroy($m yimg);
}
public function getKeycaptcha() {
return $this->keycaptc ha;
}
}
Алексей Григорьев
15.09.2017 15:43 Ответить
В демо примере вроде все работает нормально. А что вам даёт конструктор?