Генерация изображения со случайным кодом (captcha)

Чаще всего изображения со случайным кодом (так называемая captcha) используются для защиты от флуда (автоматизированного ввода сообщений), некоторые сервисы находят им применнение в качестве раздражителя (для перехода на платный вариант). В общем, может пригодиться.
PHP код следующий:

$width = 100;				//Ширина изображения
$height = 60;				//Высота изображения
$font_size = 16;   			//Размер шрифта
$let_amount = 4;			//Количество символов, которые нужно набрать
$fon_let_amount = 30;		//Количество символов на фоне
$font = "fonts/cour.ttf";	//Путь к шрифту

//набор символов
$letters = array("a","b","c","d","e","f","g");
//цвета
$colors = array("90","110","130","150","170","190","210");

$src = imagecreatetruecolor($width,$height);	//создаем изображение
$fon = imagecolorallocate($src,255,255,255);	//создаем фон
imagefill($src,0,0,$fon);						//заливаем изображение фоном

for($i=0;$i < $fon_let_amount;$i++)			//добавляем на фон буковки
{
	//случайный цвет
   	$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);
   	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 + rand(1,5);		//даем каждому символу случайное смещение
   $y = (($height*2)/3) + rand(0,5);
   $cod[] = $letter;   						//запоминаем код
   imagettftext($src,$size,rand(0,15),$x,$y,$color,$font,$letter);
}

$cod = implode("",$cod);					//переводим код в строку

header ("Content-type: image/gif"); 		//выводим готовую картинку
imagegif($src);

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

Через HTML такое изображение вызывается стандартно:

Пример работы:

защитный код

Скачать скрипт генерации защитного кода с полным набором символов и возможностью подключения своих шрифтов можно здесь secpic.zip

 

Оцените статью
Добавить комментарий

  1. Mastik

    Картинка хорошая, спасибо.Только объясните, пожалуйста, как принимающий скрипт узнает, что на ней нарисовано?

  2. Alek Veritov

    через переменную сессии.когда генерируем изображение — $_SESSION[‘secpic’] = implode(»,$cod);когда проверяем — if($_SESSION[‘secpic’]==strtolower($_POST[‘secpic’]))

  3. Winxp

    Отличный скрипт,большое спасибо

  4. seryjvolk

    в скрипте отличные буквы, мне оч понравился, а если еще и заработает у меня вообще отлично будет

  5. pati

    Спасибо. СимпотишЫне картинки. Будем ща прикручивать к фидбэку. Спасиб автору 🙂

  6. Faust

    Спасибо! Так лень было самому писать))

  7. DRONNY

    Вставляю следующий код на свою страницу:
    echo '<img src="captcha.php">';
    echo <<<HTML
    <form action="" method="post">
    Secpic: <input type="text" maxlength="4" name="secpic" /><br />
    <input type="submit" name="submit" value="Отправь меня!" />
    </form>
    HTML;
    if ($_SESSION['secpic'] == $_POST["secpic"]) {echo "Код введен правельно.";}
    Ввожу код ПРАВЕЛЬНО, но надпись "Код введен правельно." не появляется. Что делать ?

  8. drD0s

    У меня тоже самое, что и у DRONNY!
    Объясните плиз!

  9. Alek Veritov

    в captcha.php вместо $cod = implode("",$cod); надо написать $_SESSION['secpic'] = implode('',$cod);
    выведите на экран $_SESSION['secpic'] и $_POST["secpic"], посмотрите что в них и будет вам счастье …

  10. drD0s

    Разобрался!
    В самое начало страницы нужно воткнуть начало сессии!
    <php? Session_start(); ?>
    <html>

  11. CaTacLYSM

    Эмммм. А кто подскажет.
    На Denwer капча работает нормально, а вот на сервере (CentOS)Apache не рисуется!
    В чем проблема и как можно исправить?!

  12. Alek Veritov

    to CaTacLYSM: проверяйте правильность установки GD библиотеки на сервере

  13. Smile42RU

    Alek, молодец!) Кульный скрипт

  14. Сергей

    У Вас очень простые и талантливые идеи, спасибо. Вашу captcha прикрутил на свой сайт. До этого использовал вот это: recaptcha.net/plugins/php Идея там конечно хорошая, но это использование стороннего API, а это не всегда показано и слишком уж наворочено. Если надо создать лишнею проблему пользователю, то да, если надо создать некое препятствия для спам ботов, то не подойдет. Идеален в этом случаи Ваш скрипт. Не могли бы Вы ответить мне на вопрос: как Вы отлаживаете javascript скрипты? Так смотришь скрипт, вроде все элементарно, как начнешь отладку, так темный лес. По этому, по возможности, все реализую в "серверном варианте" на PHP, по крайней мере методом "научного тыка" (ошибки ведь сразу видно) удается более менее быстро написать скрипт. Хотя возможностей того же PHP стало не хватать и надоело воровать чужие скрипты на javascript. C уважением Сергей.

  15. Динар

    А есть небольшая проблема с Кешированием. У меня почему-то сессии не совпадают немного. И когда неправильно введен код, то шаблонизатор заново отображает функцию, например, регистрации, а там код тот же, что и до этого. И при этом дико несоответствуют сессии друг другу. Запаздывают примерно на одно обновление. Как это можно исправиль. Прошу прощения за сумбур.

  16. Alek Veritov

    добавляй случайный GET параметр к ссылке, что-нибудь типа /captcha.php?rand=1234, чтобы браузер и прокси не кешировали.

  17. Andy

    Здравствуйте ! Не совсем мне понятно, пожалуйста объясните пожалуйста для тех кто в танке, для чего надо стартовать новую сессию, если старт таковой уже прописан в Вашем скрипте… пробовал считывать переменную таким образом как написано выше: if($_SESSION['secpic'] == strtolower($_POST['pic'])) получал неправильный ответ иди Unknow wariable _SESSION['secpic']

  18. Alek Veritov

    Сессию, конечно, надо только один раз стартовать там, где это логично. Скрипт из архива можно использовать "как есть", поэтому там сессия стартуется. Если получаете неправильный ответ, а особенно Unknow wariable — включайте error_reporting(E_ALL) и проверяйте правильно ли стартована сессия там, где это получаете.

  19. Макс

    Не получается, прошу разобраться. В начале файла с формой ставлю старт сессии, но при вызове изображения переменная сессии не хочет запоминаться. Не могли бы вы выложить и примерный простой текст фала формы. Тоесть вы тут выложили пример но не полностью и поэтому применяя свою форму что-то да не получается.

  20. Андрей

    Картинки замечательные. К генератору никаких замечаний, всё работает, однако передачу значения кода с картинки через переменную сессии осуществить не удалось. Если можете, разъясните подробнее на рабочем примере "Форма+капча+обработчик формы и кода"

  21. Андрей

    Таки заработало! 1. Включить куки (не уверен что нужно, но читал. что без этого может не работать); 2. Удалить из браузера всю историю, куки, посещённые адреса, кеш, можно отключить кеширование страниц и т.д.(пароли оставляем:)); 3. session_star() пишем как в обработчеке формы, так и в скрипте генерации изображения. 4. Открываем "почищенный" браузер, а лучше какой-нибудь свежеустановленный альтернативный и пробуем там — должно заработать!

  22. Serega

    Здравствуйте! Сделал все как тут, картинка генерируется, но проблема вот в чем: путаюсь на той же странице вывести из сессии ТЕКСТ картинки, а он выводит почему то СТАРЫЙ, а не тот который сейчас на картинке. Да и еще при первом запуске браузера он вообще бьет ошибку на строку вывода, а когда обновляю страницу то уже выводит. но выводит текст с предыдущей картинки.

  23. Serega

    А вот код, как я это делаю: <p> <img src="secpic.php" alt="защитный код"> <?php $a = $_SESSION['secpic']; echo $a; ?> </p>

  24. Александр

    У меня проблемка, скрипт иногда выводит на картинку одно, а в переменную сессии другое, в чём может быть дело? Кэширование точно не причем. После чистки всего, кэша, истории и кук, тестил на чистом браузере…

  25. anonymous

    День добрый! Присоединяюсь к Александру. Тоже самое. Бьюсь второй день. Есть несовпадение с тем, что на картинке и с тем, что выводит $_SESSION['secpic']. В этой сессионной переменной почему то всегда значение которое было на предыдущей капче. Самое интересное что значения $_SESSION['secpic'] в скрипте моем, куда вставлена проверка и в скрипте который строит саму капчу (тот что в шапке этой статьи) РАЗНЫЕ. я это выяснил, когда добавил отсылку значения $_SESSION['secpic'] к себе на е-майл. Получилось что $_SESSION['secpic'] внутри скрипта построения капчи имеет ВЕРНОЕ значение (что и на текущей картинке), а при проверке и вызове этой переменной в своем скрипте, НЕВЕРНОЕ (предыдущее значение капчи). Помогите разобраться пожалуйста!

  26. Set

    Скрипт и капча просто супер. Что бы все заработало нужно в принимающем файле вписать следующее. $a = $_SESSION['secpic']; $a = strtolower($a); $b = $_POST['test']; $b = strtolower($b); $b = trim($b); echo "В переменной а содержится: ".$a; echo "<br>"; echo "В переменной b содержится: ".$b; echo "<br>"; if ($a == $b) { echo "куль"; } else { echo "некуль"; } ?> <br><br><br> <form name="news" method="post" action="hello.php"> <img src="blocks/secpic/secpic.php" alt="защитный код" /><br> <input type="text" name="test"> <input type="submit" name="Submit" value="Изменить"> </form>

  27. Александр

    Цитата: "У меня проблемка, скрипт иногда выводит на картинку одно, а в переменную сессии другое, в чём может быть дело?" Извиняюсь забыл уточнить, када писал это сообщение, что использовал русский алфавит, и вот он та даёт осечку такого типа. Как мне кажется эта проблема кроется в генераторе картинки. Где буквы в цикле перебираются. При использовании английских символов осечек нету, у меня точно. Set, на счёт вашего варианта попробую, может сканает 🙂 В чём суть моей проблемы, я хочу замутить капчу на русском, пока не решил проблему…

  28. Марьян

    Здравствуйте. У меня возникла такая вот проблемка. На денвере все хорошо скрипт отрабатывается и картинка выводиться, а при переносе на хостинг скрипт перестает генерировать изображение. Подскажите плиз в чем это может быть проблема.

  29. Галина

    У меня вообще выводится только альтернативный текст — подключиться к файлу никак не может

  30. Андрей

    Подскажите как сделать поле куда вписывать код

  31. Беломор

    Хорошая капча. Автору спасибо!

  32. Jasperio

    Как обновить картинку с новым кодом капTча ?

  33. MS

    Чтобы обновить изображение: <span id="captcha"><img onclick="reload(); return false;" src="sec_pic.php" alt="защитный код" style="cursor:pointer;" /></span> <script language="javascript" type="text/javascript"> function reload () { var random_value = new Date().getTime(); document.getElementById('captcha').innerHTML = '<img onclick="reload(); return false;" src="sec_pic.php" alt="защитный код" style="cursor:pointer;" />'; }; </script>

  34. ICEBERG

    Аналогичная проблема с сессией. Переменная сессии показывает предыдущее значение с картинки.

  35. MS

    в каптче сессия должна стартовать session_start(); а также сессия должна стартовать в Вашем php скрипте session_start(); в скрипте — обработчике сравниваем значения $_SESSION['secpic'] и $_POST['captcha'] if ($_POST['captcha'] != $_SESSION['secpic'] OR !$_SESSION['secpic']) echo 'error'; else echo 'good';

  36. Дмитрий

    Как перегрузить средствами php или js исходный файл(secpic.php), чтобы тот файл к которому прикручена капча не перегружался. Попробовал функцию в сообщении от 08.04.11 — не работает.

  37. MS

    не дописал 1 строку, чтобы работало нужно заменить в сообщении от 08.04 <img onclick="reload(); return false;" src="sec_pic.php" alt="защитный код" style="cursor:pointer;" /> на <img onclick="reload(); return false;" src="sec_pic.php?random_value=' + random_value + '" alt="защитный код" style="cursor:pointer;" />

  38. Дмитрий

    Автору — опишите пожалуйста как Вы реализовали проверку на ввод защитного кода "Неправильный защитный код!".

  39. wcb-tezarius

    Неплохо было бы автору обновить исходник и код вверху добавив к нему предоставленную возможность обнавления (очень полезная штука) но всеравно обоим авторам спс за скрипт

  40. Серей

    Отличный скрипт, спасибо.

  41. Mihail Zimbru

    Privet Alek, deistvitelno tvoi skript o4eni horoshii, genialnii i prostoi :). Spasibo bolishoe, ia nemnoshko ego dorobotal zdelav ego dinami4nee. Kak mne postaviti zdesi moiu dorobotku?

  42. Раиса

    Картинка красивая, но выложите, кто-нить, пож., полностью работающую капчу с проверкой введенного кода и обновлением капчи. Сенкс!

  43. Кишин

    Вообще неработает, непонятно, у меня фотрма работает вообще то даже если я вообще не введу код с картинки о_______________________О помогите 🙁

  44. Alex

    Не работает, на картинке и в переменной разные символы…:((

  45. Zakhar

    Символы на картинке и в переменной разные пока вы сеанс не перезапустите,т.к. в том же сеансе данные извлечь нельзя. Сделал свой вариант, капчу сделал ф-цией которая сразу возвращает значение кея и сохраняет картинку в гифку (имя картинки регеню по ид сессии), когда надо ф-ция вызывается, потом картинка вставляется и значение кода сразу известно.

  46. Sanchezzz T

    Спасибо то что нужно я немного переделал его //набор символов $letters = "aeioubcdfghjklmnpqrstvwxyz0123456789"; //а строку где идет выборка символов //случайный символ $letter = $letters{rand(0,strlen($letters)-1)}; а так то то нужно сэкономило мне время, не потомучто это сложно просто это готовое решение мне понравилось Спасибо автор!

  47. TEZARIUS

    Такой вопрос: как можно увеличить контрастность выводимых символов на картинке к примеру символы в фоне покрасить черным цветом а нужные для проверки сделать поярче

  48. Alek Veritov

    Цвета букв задаются как RGB тремя числами от 0 до 255. Для фона они выбираются случайно в строке 20, для основных задаются варианты потемнее в строке 11. И то и другое, естественно, можно поменять.

  49. pan_fx

    Спасибо хороший скрипт!

  50. Алексей

    Спасибо! Целый день искал наконец нашел, установился без проблем

  51. Алексей

    Можно еще и фон поменять, супер то что надо

  52. Саша

    Обалденный скрипт :))) Спасибо большое автору, все просто и без гемороя!!! и главное работает :))

  53. Kapust

    Применил данный пример, очень доволен, спасибо. Заставить работать обновление картинки из постов от 08.04.11 и 24.04.11 не получилось Зато я сочинил еще один похожий вариант с использованием библиотеки jQuery, который заработал у меня: <div class='captcha'> <img onclick='reload()' src='secpic.php'> </div> function reload() { $(".captcha").empty(); $("<img onclick='reload()' src='secpic.php?"+ new Data().getTime() +"'/>"); }

  54. kapust

    Блин криво скопировался текст, в последней строке функции надо добавить аппендТу: $("<img onclick='reload()' src='secpic.php?"+ new Data().getTime() +"'/>").appendTo(".captcha");

  55. Black Diamond

    Автор, большие благодарности за код! Работает идеально. Просто, стильно и со вкусом! Кликнул по рекламе 🙂

  56. От человека

    Fatal error: Call to undefined function imagecreatetruecolor() in F:serverwwwtestcommentssecpic.php on line 14 В моем php что нету такой функции?

  57. От человека

    ну так и было, GD2 не было подключено! Спасибо за скрипт!

  58. Виталий

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

  59. Константин

    Прекрасный скрипт. Но при использовании все равно валила куча спама пока в сессии не начал передавать не сам код в открытом виде, а md5 хэш. Видимо спам боты могут считывать переменные из сессии.

  60. от меня

    Скрипт супер, спасибо, единственный трабл, ввожу все правельно, а пишет Регистрация невозможна: код подтверждения введен не верно Из-за чего это?

  61. Anar

    Подскажите пожалуйста. Как проверить $_SESSION['secpic'] на той же странице на которую выводим капчу (например явой). Ведь в этом случае переменная методом POST не передается и соответственно $_POST['secpic'] не существует и сравнивать переменную сессии не с чем.

  62. DeepTDS

    Кстати код выбора шрифтов из папки можно упростить и улучшить, вместо: $fonts = array(); $dir=opendir($path_fonts); while($fontName = readdir($dir)) { if($fontName != "." && $fontName != "..") { $fonts[] = $fontName; } } closedir($dir); можно сделать так: $fonts = glob('fonts/*.ttf', GLOB_NOSORT); это будет полезно например если в папке со шрифтами у вас например лежит еще и .htaccess или другие файлы, так как в таком виде скрипт будет искать и использовать только файлы .ttf а не все подряд.

  63. DeepTDS

    А для обновления именно этой капчи без перезагрузки страницы я использую этот простейший JavaScript код: <img src="secpic.php?" title="Обновить картинку" onClick="this.src = 'secpic.php?'+Math.random();"/> Не забывайте также экранировать кавычки если у вас ошибки php возникают, вот так например <img src="secpic.php?" title="Обновить картинку" onClick="this.src = 'secpic.php?'+Math.random();"/>

  64. DeepTDS

    Обратные слэши тут в комментариях вырезаются поэтому второй код без экранирования тоже))) Ну думаю разобраться сможете)

  65. nikeddarn

    Здравствуйте. А как можно передать данные случайной строки в captcha.php , или забрать оттуда , если session не используется ,отключены куки? послать их при вызове GET? captcha.php/?randstr= ? это безопасно ? по другому нельзя ?

  66. Vi_ru_S

    Код рабочий для тех у кого ручки не оттуда вот мной подправленный исходник <?php session_start(); echo "<img src='captcha.php' alt='защитный код' />"; echo <<<_END <form action="test.php" method="post"> Secpic: <input type="text" maxlength="4" name="secpic" /><br /> <input type="submit" name="submit" value="Отправь меня!" /> </form> _END; if (isset($_POST['secpic'])) { $secpic = $_POST['secpic']; if ($_SESSION['secpic'] == $secpic) { echo "Код введен правельно"; } else { echo "Код введен не правильно"; } } ?>

  67. Vi_ru_S

    А код формирования каптчи в начале каптчи стартует сесия session_start(); и дальше под конец файла меняем исходник автора на вот эту бугульму $_SESSION['secpic'] = implode("",$cod); //переводим код в строку

  68. Vi_ru_S

    Автору спасибо:) Кликнул по рекламке:)

  69. vitys

    Такая проблема-часто при регистрации или скачке файлов требуется ввести данные с картинки и тут проблема(последние несколько месяцев)-пишет текст введён не правильно(использую вай-фай): летебит, депозит и уйма других всё таже проблема, со смарта и с ноута(разные браузеры,версии винды)-всё равно, раньше вводил без осечек, только с яндекс народа вводится нормально. Кто нибудь знает решение?

  70. vitys

    Вот ещё здесь сработало.

  71. Андрей

    Спасибо, очень круто

  72. techncode

    В конце не мешало бы еще поставить imagedestroy($src);

  73. Ростислав

    Народ Session не обновляется, сравнение не срабатывает

  74. Анатолий

    Большое спасибо! Отличный скрипт

  75. Сергей

    Не могу это приладить в Joomla 2.5. В сессии пусто. Подскажите, пожалуйста, как эту красивую штучку приладить в форму регистрации?

  76. Сергей

    На хосте заработало! Пришлось добавить в верху secpic.php: $mainframe =& JFactory::getApplication('site'); $mainframe->initialise(); и внизу: $s=implode('',$cod); $session =& JFactory::getSession(); $session->set('secpic', $s); $_SESSION['secpic'] =$s; Только так заработало (. Будем проверять. Автору — Спасибо!

  77. Василий Васильевич

    Примного благодарен за скриптик

  78. userX

    Спасибо большое за скрипт! Очень полезная вещь!

  79. Павел

    Спам боты пробивают эту captch-у. Как можно защитить передачу правильного ответа от ботов?

  80. Павел

    Пояснения к предыдущему комментарию: У меня пробивали не через captcha , а SQL-запросами. Проверил бесплатной программой NetSparker и нашел как боты обходят защиту код-картинка.

  81. Андрей

    Спасибо! То, что надо.

  82. Михаил

    Все красиво и удобно, только проверка правильности ввода не работает. session_start(); на обоих страничках есть. На страничке с формой значение переменной $_SESSION['secpic'] недоступно, хотя в файле sess_ID значение сохраняется. Вот содержимое: secpic|s:5:"dbsp6"; В чем дело? Вторую неделю не могу ни чего сделать.

  83. ilma55

    а вот бы еще REFRESH добавить надо не подскажите?

  84. ilma55

    ха ха. я сделал =) <img src="<?=SITE_PATH?>views/script/kartinka.php?sid=<?php echo md5(time()) ?>" id="cap_img"> <a href="#"onclick="document.getElementById('cap_img').src = '<?=SITE_PATH?>views/script/kartinka.php?sid=' + Math.random(); return false">Refresh</a>

  85. Михаил

    "ilma55 ха ха. я сделал =)" —————————— А проверку на правильность ввода как делаете? Ведь без этого это бесполезная вещь, хоть как ее раскрась. Что интересно, здесь-то проверка работает, специально проверил, а я не могу сделать.

  86. Михаил

    Интересно

  87. Андрей

    В smarty интегрировать не получается, может кто знает как это делается?

  88. ro$ven

    Спасибо огромное, очень выручил своим скриптом, действительно классный 😉

  89. cupoma58

    никакой картинки не получилсь, а-жаль…

  90. Иванов Михаил

    Вот спасибо большое за простой и красивый код. Кстати чтоб при нажатии на картинку генерировалась новая нужно всего то добавить onClick, и стиль просто для отображения руки <img src="sec_pic.php" onclick="this.src='sec_pic.php'" style="cursor:pointer;">

  91. Аликс

    Спасибо, очень помогло!!!

  92. Crack1

    Надо в файли генерации картинки вставить Session_start() и в самый верх вашего индексного файла (index.*) тоже самое. И всё 🙂

  93. Crack1

    А это обновлять картинку: <a href="javascript:void(0);" onclick="document.getElementById('capcha-image').src='captcha.php?rid=' + Math.random();">Обновить картинку</a>

  94. Crack1

    А еще я заменил строку записи в сессию на $_SESSION['feedback']=md5(implode('',$cod)); это чтобы зашифрованная была сразу. потом проверяем: if(trim(md5($_POST['code']))==$_SESSION["feedback"])… — а есчооооо я заметил, что при изменении размера (ширины) картинки буквы всё также толкутся у левого края. оптимально-красиво до 120px ширину делать. Возможно для красоты надо добавлять количество выводимых на картинку символов. Крутой скрипт! красивый! какже я его раньше то не замечал! 🙂

  95. Sanek_OS9

    Капча красивая и работает прекрасно. Спасибо!

  96. some

    Не отображается само изображение. Только alt Я так понимаю проблема в GD2? Помогите, пожалуйста.

  97. 55

    Шикарный скрипт спасибо

  98. bababudu007

    Так все работает.