Фев
Как сделать капчу (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 Ответить
В демо примере вроде все работает нормально. А что вам даёт конструктор?