CAPTCHA Perl. Генерация при помощи ImageMagick

Небольшая функция генерации капчи для perl при помощи вызова imagemagick через библиотеку Image::Magick.
Может пригодиться в том случае, когда хостер не позволяет устанавливать свои модули для perl (например GD::SecurityImage или Auchten::Captcha). Модуль для работы с ImageMagick не стоит по умолчанию разве что у самого нерадивого хостера.
Функцию можно использовать как библиотечный вызов, при вызове передавать имя файла и строку для генерации капчи.

Код самой функции:


#!/usr/bin/perl
# Генератор капчи. Идея и параметры вызова Convert взяты с captcha.ru (http://captcha.ru/captchas/multiswirl/).
# Реализация под библиотеку Image::Magick для perl - dimio (dimio.org).
# 27.09.2009
use Image::Magick;
sub CreateCapImage($$){
my($cap_string,$filename) = @_;
my $font = 'times.ttf';
my $pointsize = 70;
my $path = './';

my $image = new Image::Magick;

# 1. Создаём поле 300x100 белого цвета.
$image->Set(size => '300x100');
$image->ReadImage('xc:white');
# 2. Печатаем черным с антиалиасингом
$image->Set(
type => 'TrueColor',
antialias => 'True',
fill => 'black',
# строку STRING шрифтом $font размером $pointsize
font => $font,
pointsize => $pointsize,
);
$image->Draw(
primitive => 'text',
points => '20,70', # ориентация строки текста внутри картинки
text => $cap_string, # что печатаем
);
# 3. Подвинуть центр влево на 100 точек +случайная флуктуация
$image->Extent(
geometry => '400x120', # меняем размер картинки
);
$image->Roll(
x => 101+int(rand(4)),
);
# 4. Первый swirl на случайный угол (от 37 до 51)
$image->Swirl(
degrees => int(rand(14))+37,
);
# 5. Подвинуть центр вправо на 200 точек, тоже со случайной флуктуацией
$image->Extent(
geometry => '600x140', # меняем размер картинки
);
$image->Roll(
x => 3-int(rand(4)),
);
# 6. Второй поворот (от 20 до 35)
$image->Swirl(
degrees => int(rand(15))+20,,
);
# 7. Окончательная обработка и вывод
$image->Crop('300x100+100+17');
$image->Resize('150x50');

$filename = $path . $filename;
$filename .= '.png';
open(IMAGE,'>',$filename) or die $!;
$image->Write(file=>\*IMAGE, filename=>$filename);
close(IMAGE);

return $filename;
}

1;

Пример вызова:


# Вызов капчи из скрипта
my $num1 = int(rand(11))+int(rand(3));
my $num2 = int(rand(8))+int(rand(4));
my $sum = $num1+$num2;
my $cap_string = $num1.'+'.$num2.'=';
my $cap_digest = md5_hex($sum+rand(100)+rand(50));
my $cap_url = &CreateCapImage($cap_string,$cap_digest);
$cap_url =~ s|/home/dimioorg/public_html/dimioorg||;
$cap_url = 'https://dimio.org'.$cap_url;
print $query->em(""),
$query->textfield(
-name => 'cap_value',
-size => 2,
-maxlength => 2,
);

В результате на странице будет выведена картинка с символами вида «12+7=». Строка в принципе может быть какой угодно.

Кому лень копипастить — может скачать функцию captcha.pl и три ttf шрифта. А еще для генерации капчи можно использовать специальный модуль Authen::Captcha.

Написано на правах памятки для себя, но вдруг кому пригодится :)

13 мыслей о “CAPTCHA Perl. Генерация при помощи ImageMagick”

  1. Что-то не работает!
    Рисунок — просто белый прямоугольник,без текста, а потом
    вываливается на
    print $query->em(«»),
    $query->textfield(
    -name => ‘cap_value’,
    -size => 2,
    -maxlength => 2,
    );

    с сообщением
    Can’t call method «em» on an undefined value at /home/…….

    1. В примере указано так:

      print $query->em(««),

      ,а вы передаёте пустую строку.
      Модуль CGI подключен кстати?

      Что касается рисунка — во-первых — шрифт указан правильно? Во-вторых — можно покрутить параметры генерации. У меня получалась нормальная картинка с капчей при указанных в примере параметрах.

  2. Сделал так:
    $query = new CGI;
    print $query->em(«»),
    $query->textfield(
    -name => ‘cap_value’,
    -size => 10,
    -maxlength => 5,
    );
    все заработало, но картинка пустая :(

  3. вот сделал капчу… все работает.
    а как правильно проверять ее и ввод юзера ?

    1. Я бы вычислял хэш сгенерированного слова для капчи и хэш пользовательского ввода, а затем сравнивал их. Модуль Digest::MD5 в помощь.

  4. ну хэш пользовательского ввода вычислить без проблем… а вот хэш капчи как ?? он же уже забыт, т.к. скрипт отработался на выводе капчи ). да и вобще это разные скрипты могут быть — один выводит капчу, а другой принимает ввод… вот и заморочка у меня тут (

    1. Хэш капчи класть в файл или иную БД (в файл логичней и проще, но если уже есть БД для движка — почему бы не создать там таблицу), отработавшие (и при желании — протухшие) хэши капч удалять. Для удобства можно капчам идентификаторы присваивать некие.

  5. Скачал исходный код, у меня создался файл нулевого размера cap_test.png.
    Ubuntu 14+perl 5.18 +ImageMagick 6.9.0
    Понимаю, что проблема у меня. Прошу у гуру помочь разобраться

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

Ваш адрес email не будет опубликован.