Домашние Картинки разработка веб-сайтов в Челябинске
(351) 777-94-64info@homepictures.ru
/Полезное/Статьи для веб-мастера/Модифицированная капча

Модифицированная капча

В статье защита форума phpbb рассматривался прием замены стандратной капчи на самодельную. Трудность применимости приведенного метода заключалась в необходимости генерации файла шрифта в формате, требуемом функцией imageloadfont. Сейчас мы приведем метод выведения капчи с применением широко распространненных TTF шифтов.

PHP функция imagettftext (из графической библиотеки GD/GD2) позволяет выводить текст шрифтом TrueType и кроме того задавать угол наклона для выводимого текста. TTF-файлы в Windows можно взять из папки "каталог установки windows\Fonts\" (обычно C:\Windows\Fonts\). Для вывода капчи нам потребуется следующий код.

<?php
$fontsize = 16; //размер шрифта
$font = $_SERVER['DOCUMENT_ROOT'].'/verdana.ttf'; //полный путь до файла шрифта
$bg_file = $_SERVER['DOCUMENT_ROOT'].'/rnumberfon.png'; //полный путь до файла фона
$a = imagettfbbox ($fontsize, 0, $font, 'M'); // получаем размеры одной буквы шрифта
$letter_w = abs($a[2]-$a[0]); // ширина буквы M
$letter_h = abs($a[1]-$a[7]); // высота буквы M
$im = @imagecreatefrompng($bg_file); // создаем изображения из файла фона
$textcolor = imagecolorallocate($im, 255, 255, 64); // цвет текста
$nChars = strlen($code); // число символов в коде
$cell_w = round(imagesx($im)/$nChars); // ширина ячейки для одной буквы
$pich = imagesy($im); // высота картинки
srand(time()); // инициируем счетчик случайных чисел
$indent = round(($cell_w-$letter_w)/2); //отступ от границы ячейки для буквы
if($indent<0) $indent = 0;
$bottom = round(($pich + $letter_h)/2);
$top = $bottom - $letter_h; for($i=0; $i<$nChars; $i++){ $letter = charcode($code{$i}); //получаем код символа для функции imagettftext $fontangle = 30 * round(2 * rand() / getrandmax ()-1); //случайный угол наклона в пределах 30° $indenty = $top * 0.5 * round(2 * rand() / getrandmax() - 1); // случайный отступ по вертикали imagettftext($im, $fontsize, $fontangle, $cell_w*$i+$indent, $bottom-$indenty, $textcolor, $font, $letter);//выводим букву } //выводим заголовки для выводимого файла header('Content-Type: image/png');
header ('Expires: Mon, 26 Jul 1997 05:00:00 GMT');
header ('Last-Modified: '.gmdate('D, d M Y H:i:s').' GMT');
header ('Cache-Control: no-cache, must-revalidate');
header ('Pragma: no-cache'); ImagePng($im); // выводим полученное изображение в браузер // функция для преобразования кода русской буквы в html код function charcode($char){ $charcode = ord($char); return ($charcode>191) ? "&#" . (1040 + $charcode - 192). ";" : $char; } exit(); ?>

На вход данного кода должна поступить определенная переменная $code, которая содержит выводимый графический код. Кроме того вам возможно понадобится подправить пути к файлам и другие параметры для более точного выполнения вашей задачи.

Рассмотрим как применить данный код для вывода капчи на форуме phpBB 2-й версии.

Вставляем в файл includes/usercp_confirm.php после строк

// If we have a row then grab data else create a new id
if ($row = $db->sql_fetchrow($result))
{
	$db->sql_freeresult($result);
	$code = $row['code'];
}
else
{
	exit;
}

следующий код

header ("Expires: Mon, 26 Jul 1997 05:00:00 GMT");
header ("Last-Modified: " . gmdate("D, d M Y H:i:s") . " GMT");
header ("Cache-Control: no-cache, must-revalidate");
header ("Pragma: no-cache");
$fontsize = 16;
$font = diraname(__FILE__).'/verdana.ttf';
$bg_file = dirname(__FILE__).'/rnumberfon.png';
$a = imagettfbbox ($fontsize, 0, $font, 'M');
$letter_w = abs($a[2]-$a[0]);
$letter_h = abs($a[1]-$a[7]);
$im = @imagecreatefrompng($bg_file);
$textcolor = imagecolorallocate($im, 255, 255, 64);
$nChars = strlen($code);
$cell_w = round(imagesx($im)/$nChars);
$pich = imagesy($im);
srand(time());
$indent = round(($cell_w-$letter_w)/2);
if($indent<0) $indent = 0;
$bottom = round(($pich + $letter_h)/2);
$top = $bottom - $letter_h;
for($i=0; $i<$nChars; $i++){
	$letter = charcode($code{$i});
	$fontangle = 30 * round(2 * rand() / getrandmax ()-1);
	$indenty = $top * 0.5 * round(2 * rand() / getrandmax() - 1);
	imagettftext($im, $fontsize, $fontangle, $cell_w*$i+$indent, $bottom-$indenty, $textcolor, $font, $letter);
}
imagepng($im);
function charcode($char){
	$charcode = ord($char); 
	return ($charcode>191) ? "&#" . (1040 + $charcode - 192). ";" : $char; 
}
exit();

Что нам нужно еще? Нам нужны

Имена файлов естественно могут быть названы, как вам удобно. Загрузить их нужно в каталог форума includes.

Все – ваша каптча для форума phpBB готова!

Усложним нашу капчу. Открываем файл includes/usercp_register.php и заменяем строку

$confirm_chars = array('A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J',  'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T',  'U', 'V', 'W', 'X', 'Y', 'Z', '1', '2', '3', '4', '5', '6', '7', '8', '9');

на строки

$string = 'АБВГДЕЖЗИЙКЛМНОПРСТУФХЦЧШЩЪЫЬЭЮЯ';
for($i=0; $i < strlen($string); $i++) $confirm_chars[$i] = $string{$i};

Это русский алфавит, используемый для отображения кода. Букву Ё выкинули из алфавита, т.к. шрифтом verdana, она отображается некорректно. Вы можете расширить этот алфавит какими угодно символами, добавив их в конец строки.

В данном случае, пользователю будет выдаваться код русскими буквами, что отсечет спамеров, не пользующихся русской клавиатурой.

Ну и для модификации и усложения кода вы также можете

Удачи вам с борьбе со спамерами.

Ссылки по теме:

Защищаем PHPBB от спама и ботов или как изменить стандартное визуальное подтверждение (captcha) в PHPBB

Обсуждение на официальном форуме phpBB. Preventing SPAM - Bots and Humans (на английском языке)