PHP. Рисуем простую капчу.
PHP

Здравствуйте дорогие друзья!

Сегодня кое-что о защите сайта от роботов. На сегодняшний день наиболее эффективным способом остается использование картинки, которую предлагается «распознать» и напечатать результат в соответствующем поле. То есть закрыть действие на капчу. Самая распространенная ситуация: защитить от спам-роботов комментарии, или регистрацию на вашем сайте.

Ну, поскольку сайты чаще всего строятся на PHP, то и наша функция будет реализована именно на этом языке программирования.

Предлагаемый ниже способ позволяет генерировать вот такие замечательные картинки:
captcha

Поскольку фон состоит из букв и цифр, то «распознать» такую капчу с помощью компьютера будет довольно затруднительно. То есть, она обеспечивает сравнительно высокую степень защиты.

Давайте перейдем непосредственно к коду и разберем в комментариях что и как:

function showcaptcha()
{
    //Указываем путь к папке, где у нас лежит шрифт
    $path = $_SERVER['DOCUMENT_ROOT'] . '/fonts/';
    $width = 200;               //Ширина капчи
    $height = 60;               //Высота
    $font_size = 16;            //Размер шрифта
    $let_amount = 6;            //Количество символов в нашей капче
    $fon_let_amount = 100;      //Количество знаков, составляющих фон
    $font = $path."cour.ttf";   //Непосредственно путь к шрифту
 

    /* Набираем алфавит, из которого будем генерировать случайным
     * образом текст на нашей картинке. При этом исключаем похожие
     * символы для удобства пользователей. Например 1 и I
     */
    $letters = array("a","b","c","d","e","f","g","h","i","j","k","m","n","p","q","r","s","t","u","v","w","x","y","z",2,4,5,6,7,8,9);
    //Ну тут, так сказать, гамма из которой генерируется цвет буквы
    $colors = array("90","110","130","150","170");  
 
    $src = imagecreatetruecolor($width,$height); //Создаем холст
    $fon = imagecolorallocate($src,255,255,255); //Генерируем белый цвет. Так положено.
    imagefill($src,0,0,$fon);            //Заполняем им холст. Чтобы не прозрачным был.
 
    for($i=0; $i < $fon_let_amount; $i++)  //Генерируем фон
    {
        /* Определяем цвет буквы случайным образом.
         * Первым параметром идет холст. Потом цвет в формате RGB. Затем прозрачность,
         * чтобы наш фон не "забивал" основные буквы.
         */
        $color = imagecolorallocatealpha($src,rand(0,255),rand(0,255),rand(0,255),100); 
        //Выбираем случайным образом букву
        $letter = $letters[rand(0,sizeof($letters)-1)]; 
        //Делаем буквы чуточку разными по размеру
        $size = rand($font_size-2,$font_size+2); 

        /* Ну здесь происходит непосредственно выбранной ранее буквы, выбранным цветом.
         * Объяснять что означает каждый параметр не буду, вы можете сами почитать:
         * http://php.net/manual/ru/function.imagettftext.php
         */                                           
        imagettftext($src,$size,rand(0,45),
                     rand($width*0.1,$width-$width*0.1),
                     rand($height*0.2,$height),$color,$font,$letter);
    }
 
    // Аналогичным образом генерируем основные буквы капчи
    for($i=0;$i < $let_amount;$i++)
    {
        //Генерируем цвет по нашей "гамме".
        $color = imagecolorallocatealpha($src,$colors[rand(0,sizeof($colors)-1)],
                                              $colors[rand(0,sizeof($colors)-1)],
                                              $colors[rand(0,sizeof($colors)-1)],rand(20,40)); 

        $letter = $letters[rand(0,sizeof($letters)-1)];
        //Здесь уже покрупнее делаем
        $size = rand($font_size*2-2,$font_size*2+2);
        //А это сдвиг буквы. Пытаемся сделать его случайным
        $x = ($i+1)*$font_size*1.5 + rand(1,5);
        //Здесь генерируем сдвиг по вертикали. Чтобы буквы "плясали" вверх-вниз
        $y = (($height*2)/3) + rand(0,5);                            
        /* Сохраняем каждую букву в массив. Потом соединим в строку.
         * Можно и сразу фигачить конкатенацией, но я не очень люблю
         */
        $cod[] = $letter;

        //Печатаем букву, как и в прошлый раз с фоном.
        imagettftext($src,$size,rand(-20,20),$x,$y,$color,$font,$letter);
    }
 
    $cod = implode("",$cod); //Ну тут делаем из массива строку...

    /*Записываем набор символов в сессию. Ну или куда-нибудь сохраняем.
     * Не забудьте сессию стартовать сначала. Надеюсь, умеете? =)
     */
    $_SESSION['captcha']=$cod;
    header ("Content-type: image/gif"); //Отправляем заголовок браузеру. 
    imagegif($src); //И выводим саму картинку.
}

Потом где-нибудь на страничке пишем форму и рядышком что-то типа

    <img src="/captcha.php" />

А в том файле вызов нашей функции как раз… И старт сессии сначала! 😉

Как проверять капчу подробно объяснять не буду: берете значение из формы, сравниваете с тем, что у нас в сессии сохранено. Совпадает, значит хорошо. Нет — пишем что не верно введены символы с картинки.

Всем удачной борьбы с роботами!

Да, кстати, у вас естественно должна быть установлена библиотека GD.

  • А разве header(); не должна быть самой первой командой в скрипте и стоять раньше всех команд вывода на экран?

    • root4root aka admin:

      Все правильно, но тут нет никакого вывода до отправки заголовков через header. )

Добавить комментарий