Добавляем CAPTCHA к форме. Пример PHP скрипта, использующего AJAX.

Владимир | | Ajax, CodeIgniter, JavaScript.

Логотип CAPTCHA
О том, что такое CAPTCHA и зачем она нужна, думаю рассказывать не нужно. Все, кто хоть раз регистрировался на каком-нибудь интернет-сервисе, прекрасно понимают, о чем идет речь.

В этой статье мы посмотрим, как создать несложную CAPTCHA, добавить ее к форме, и проверить правильно ли посетитель ввел ее значение. Посмотреть действующий пример можно здесь.

Сразу хочу отметить, что речь пойдет именно о работе с CAPTCHA, а не о создании рисунка для нее.

Поэтому мы используем готовую библиотеку для создания рисунка CAPTCHA. Библиотека называется достаточно незамысловато – captcha и может использоваться вместе с фрэймворком CodeIgniter. В описании библиотеки приведен пример ее использования на обычной странице, поэтому мы рассмотрим вариант проверки с применением технологии ajax.

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

Разница заключается в том, что в случае captcha посетитель должен ввести заранее определенное значение (обычно оно нарисовано на картинке). Значит, мы должны каким-то образом сохранить это значение, а затем использовать для проверки.

Для хранения данных captcha мы используем базу данных, а отличать посетителей друг от друга будем по их ip адресу.

Примечание. Это, конечно, не единственное решение.

Т.к. в этом примере мы используем CodeIgniter, то предположим, что у нас есть контроллер (captchademo.php), который содержит два метода: index() (создает страницу с формой) и ajaxcheck() (выполняет проверку и обработку данных формы). Отправку ajax запроса и обработку его результатов будут выполнять функции, размещенные в checkcaptcha.js. Чтобы сократить количество JavaScript кода, используем библиотеку prototype.

Принцип работы captcha показан на диаграмме.

Диаграмма работы с CAPTCHA (миниатюра)

Рассмотрим его немного подробнее.

При входе на страницу с формой, выполняется метод index контроллера, который создает страницу с формой и отправляет ее браузеру.

function index() {
	$this->load->library('captcha');
	//создаем captcha
	$vals = array(
		'word' => mt_rand(0, 9999),
		'img_path' => str_replace(SELF, "", FCPATH).'uploads'.DIRECTORY_SEPARATOR,
		'img_url' => base_url().'uploads/',
		'font_path' => str_replace(SELF, "", FCPATH).'system'.DIRECTORY_SEPARATOR.'fonts'.DIRECTORY_SEPARATOR.'AntsyPants.ttf',
		'img_width' => '100',
		'img_height' => '30',
		'expiration' => '7200'
	);
	$cap = $this->captcha->create_captcha($vals);
	//добавляем запись с данными captcha в БД
	$data = array(
		'captcha_id' => '',
		'captcha_time' => $cap['time'],
		'ip_address' => $this->input->ip_address(),
		'word' => $cap['word']
	);
	$query = $this->db->insert_string('captcha', $data);
	$this->db->query($query);

	$pageData['title'] = "Тестирование CAPTCHA";
	$pageData['scripts'] = array('js/prototype.js', 'js/checkcaptcha.js');
	$pageData['image'] = $cap['image'];
	$this->load->view('header', $pageData);
	$this->load->view('captcha');
	$this->load->view('footer');
}

В строках 2-13 мы загружаем библиотеку captcha и создаем массив с настройками.
word – текст, нарисованный на картинке;
img_path – путь к изображениям;
img_url – адрес изображений;
font_path – путь к файлу со шрифтом, который будет использоваться (/system/fonts/);
img_width – длина картинки;
img_height – высота картинки;
expiration – время «жизни» (в секундах).

Как видите, ничего сложного, самое главное правильно указать путь и адрес файлов с картинками (для этого использована функция base_url() и несколько констант, которые инициализируются в index.php).

Примечание. Для того, чтобы приведенный здесь код работал, библиотека captcha должна быть размещена в папке system/application/libraries либо system/libraries. Кроме того, необходимо создать таблицу в БД для хранения данных captcha:

CREATE TABLE `captcha` (
  `captcha_id` bigint(13) unsigned NOT NULL auto_increment,
  `captcha_time` int(10) unsigned NOT NULL,
  `ip_address` varchar(16) NOT NULL default '0',
  `word` varchar(20) NOT NULL,
  PRIMARY KEY  (`captcha_id`),
  KEY `word` (`word`)
) ENGINE=InnoDB  DEFAULT CHARSET=utf8 AUTO_INCREMENT=1 ;

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

После того, как объект captcha создан, добавляем его данные в БД (строки 15-22).

А дальше – загружаем представление, которое содержит нашу форму. Обратите внимание, url рисунка передан в $pageData['image'] (строка 26). Таким образом, в представлении будет создана переменная $title с адресом рисунка.

Сама форма выглядит следующим образом:

<form action="#" method="post">
<p>
<label for="checkcode">Введите число, изображенное на картинке *: </label>
<input type="text" size="30" id="checkcode" />
<?php echo $image; ?>
</p>
<p>
<input type="button" value="Проверить" id="sendBtn" onclick="check('<?php echo site_url(); ?>', '<?php echo base_url(); ?>')" />
</p>
</form>
<div id="res"></div>

Эта форма содержит только одно поле – для ввода captcha.

После нажатия на кнопку «Проверить» будет вызвана функция check (находится в файле checkcaptcha.js), которая в качестве параметров получит адрес сайта. Эта информация используется для отправки запроса и вставки анимации (о ней чуть ниже).

Примечание. В строках 27 и 29 метода index() мы загрузили представления с заголовком и хвостовиком страницы. Хвостовик не содержит ничего кроме закрывающих тегов, а вот заголовок загружает js библиотеки.

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN">
<html xmlns="http://www.w3.org/1999/xhtml" lang="ru">
<head>
<title><?php echo $title; ?></title>
<meta http-equiv="content-type" content="text/html; charset=UTF-8" />
<link rel="stylesheet" type="text/css" href="<?php echo base_url(); ?>css/styles.css" />
<?php
if (isset($scripts)) {
	foreach ($scripts as $script) {
		echo "<script src=\"".base_url().$script."\" type=\"text/javascript\" />\n";
	}
}
?>
</head>
<body>

Теперь рассмотрим, функцию check, которая вызывается при нажатии на кнопку «Проверить».

function check(siteUrl, baseUrl) {
	var pars = $H({check:$('checkcode').value});
	$('res').innerHTML = '<img src=\"' + baseUrl + '/css/images/ajax-loader.gif' + '\" alt=\"Отправка данных...\" />';
	$('sendBtn').style.display = "none";
	new Ajax.Request(
		siteUrl + "/captchademo/ajaxcheck",
		{
			parameters:pars.toQueryString(),
			onComplete: function(transport) {
				var response = eval("(" + transport.responseText + ")");
	            $('sendBtn').style.display = "";
				if (response.state == "OK") {
					$("res").innerHTML = "Правильно!<br />";
				}
				else {
					$("res").innerHTML = response.errMessages;
				}
			},
			onFailure: function() {
				alert("Error");
			}
		}
	);
}

В строке 2 мы читаем введенное значение.

После этого, прячем кнопку «Проверить» и вставляем картинку с анимацией (строки 2 и 3).

Примечание. Я сделал картинку с анимацией с помощью сервиса www.ajaxload.info.

В строке 5 создаем и отправляем запрос.

Если запрос выполнен успешно, то для обработки его результатов будет вызвана анонимная функция, определенная в параметре onComplete (строки 9-18).

Эта функция возвращает на место кнопку «Проверить» (строка 11) и отображает сообщение с результатом.

Теперь переходим к коду обработки ajax запроса на стороне сервера. Напомню, что этот код находится в методе ajaxcheck() контроллера.

function ajaxcheck() {
	$this->load->library('validation');

	$rules['check'] = "required|callback_captcha_check";
	$this->validation->set_rules($rules);

	$fields['check'] = "captcha";
	$this->validation->set_fields($fields);

	if ($this->validation->run()) {
	    $res['state'] = "OK";
		//тут будет код, обрабатывающий данные формы
	}
	else {
		$res['state'] = "ERR";
		$res['errMessages'][] = $this->validation->check_error;
	}
	echo json_encode($res);
	return;
}

Здесь мы, прежде всего, подключаем библиотеку validation. О ней можно почитать в статье «Проверка данных из форм (CodeIgniter)», поэтому подробно останавливаться на ее работе я не буду.

Главное, обратите внимание, что для проверки полученного значения мы создали правило callback_captcha_check (строка 4), а это значит, что нужно написать метод, который эту проверку будет выполнять.

function captcha_check($str) {
	$exp = time() - 7200;
	$this->db->query("DELETE FROM captcha WHERE captcha_time < ".$exp);
	$qFind = "SELECT COUNT(*) AS count FROM captcha WHERE word = ? AND ip_address = ? AND captcha_time > ?";
	$data = array($this->input->post('check'), $this->input->ip_address(), $exp);
	$query = $this->db->query($qFind, $data);
	$row = $query->row();

	if ($row->count == 0) {
		$this->validation->set_message('captcha_check', 'Введенное число не соотвествует, изображенному на рисунке');
		return FALSE;
	}
	else {
		return TRUE;
	}
}

Здесь мы выполняем все операции, приведенные на диаграмме в начале статьи. А именно:
удаляем из БД все устаревшие записи (строки 2 и 3);
пробуем найти запись, у которой значения полей ip_address и word совпадают с переданными;
— если такая запись найдена, возвращаем true;
— в противном случае – создаем сообщение с описанием ошибки и возвращаем false.

После выполнения проверки метод ajaxcheck() формирует ответ (строки 11-16) и отправляет его браузеру.

Примечание. Ответ отправляется в формате json. Подробнее о нем можно почитать в статье «Использование JSON в web приложениях».

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

Как видите, работа с библиотекой достаточно простая, хотя многие операции приходится выполнять вручную (в смысле писать самостоятельно код).

Source

До встречи!

  • MAX

    Интересно, спасибо.

    Не могу понять только зачем использовать базу данных? Капчу (правильное значение) можно сохранить в сессии или, если попроще, то прямо в форме (hidden) указывать.

    И еще небольшой офтоп. Диаграммы вы в чем делаете? 🙂

    • Сохранять в сессии или БД, по-моему, без разницы.
      Но из БД удобнее удалять устаревшие картинки и записи.
      А использование hidden может создать проблемы. Достаточно просто написать скрипт, который легко обойдет эту защиту.

      Диаграммы рисую в StarUML.
      Программка неплохая, но есть недостаток — нужно постоянно нажимать F5 иначе вместо кириллицы рисует кракозябры.

      • MAX

        Спасибо за ссылку. Попробую. Я использую Diagram Designer

        • А Diagram Designer чем-то не устраивает или просто хочется попробовать что-то другое? 😉

      • Nas

        в сессии не надо ничево удалять… (или я што то не так понимаю..)
        или можно просто $_SESSION['word']==»»; помоєму ето проще и удобне..
        у себея сделал именно так.

        • Я имел ввиду удаление файлов с картинками.

  • MAX

    Интересно, спасибо.

    Не могу понять только зачем использовать базу данных? Капчу (правильное значение) можно сохранить в сессии или, если попроще, то прямо в форме (hidden) указывать.

    И еще небольшой офтоп. Диаграммы вы в чем делаете? 🙂

    • Сохранять в сессии или БД, по-моему, без разницы.
      Но из БД удобнее удалять устаревшие картинки и записи.
      А использование hidden может создать проблемы. Достаточно просто написать скрипт, который легко обойдет эту защиту.

      Диаграммы рисую в StarUML.
      Программка неплохая, но есть недостаток — нужно постоянно нажимать F5 иначе вместо кириллицы рисует кракозябры.

      • MAX

        Спасибо за ссылку. Попробую. Я использую Diagram Designer

        • А Diagram Designer чем-то не устраивает или просто хочется попробовать что-то другое? 😉

      • Nas

        в сессии не надо ничево удалять… (или я што то не так понимаю..)
        или можно просто $_SESSION['word']==»»; помоєму ето проще и удобне..
        у себея сделал именно так.

        • Я имел ввиду удаление файлов с картинками.

  • Мммм… как же приятно видеть диаграммы деятельности в виде алгоритма 😉

    Кстати — в чём наприсовано? У меня RR 2003 — там немного по-другому просто выглядит 😎

    • Нарисовано в StarUML.
      Программка хорошая, но есть несколько недостатков. В целом, работает быстро, рисовать удобно.

    • Кстати, RR — это Rational Rose?
      Давно хотел попробовать, но все не хватает времени. Один вопрос, UML2 поддерживается полностью? В StarUML — нет.

  • Мммм… как же приятно видеть диаграммы деятельности в виде алгоритма 😉

    Кстати — в чём наприсовано? У меня RR 2003 — там немного по-другому просто выглядит 😎

    • Нарисовано в StarUML.
      Программка хорошая, но есть несколько недостатков. В целом, работает быстро, рисовать удобно.

    • Кстати, RR — это Rational Rose?
      Давно хотел попробовать, но все не хватает времени. Один вопрос, UML2 поддерживается полностью? В StarUML — нет.

  • Вобще неплохо все растолковал…

  • Вобще неплохо все растолковал…

  • Есть такие капчи, которые создаются вообще без всяких принципов… Вспомнить ту же капчу Made-cat, который щас спамится как сумасшедший. Просто для отвода глаз…

    • Каждый разработчик (владелец) сайта решает этот вопрос сам… он же и расхлебывает последствия.

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

  • Есть такие капчи, которые создаются вообще без всяких принципов… Вспомнить ту же капчу Made-cat, который щас спамится как сумасшедший. Просто для отвода глаз…

    • Каждый разработчик (владелец) сайта решает этот вопрос сам… он же и расхлебывает последствия.

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

  • Отличная статья. Обязательно добавлю у себя на сайте. Потому что роботы в последнее время проявляют завидную активность 🙂 автору спасибо.

  • Отличная статья. Обязательно добавлю у себя на сайте. Потому что роботы в последнее время проявляют завидную активность 🙂 автору спасибо.

  • Мне одному кажеться, что блок с кодом нужно сделать побольше?

    • Может быть. Сделать это несложно. Посмотрим что получится 🙂 .
      В любом случае спасибо за совет.

  • Мне одному кажеться, что блок с кодом нужно сделать побольше?

    • Может быть. Сделать это несложно. Посмотрим что получится 🙂 .
      В любом случае спасибо за совет.

  • Tazman

    Вот бы еще туториал по созданию странички загрузки файлов с использоанием Аякс и CI 😉

    • Wave

      Да, загрузку файлов аджаксом на CI тоже не прочь был бы увидеть.

      И ещё один то ли совет, то ли просьба по юзабельности сайта.
      Блок: «Вы можете отслеживать обсуждение … или трекбек с Вашего сайта.» — визуально от самих комментариев отделите. Хотя бы чертой hr. Будет лучше восприниматься.

      • Спасибо за совет, попробую изменить.

    • Вообще-то у меня была похожая идея.
      В CI есть библиотека «upload», с которой довольно легко работать. А загрузка с помощью AJAX или без него отличается только тем, что нужно писать JavaScript функцию.
      В общем, я подумаю что включить в эту статью.

    • Я был неправ. В смысле терминологии. Загрузить файл с помощью AJAX нельзя. Но можно реализовать загрузку так, что посетитель не заметит разницу.

      В общем, следующий пост на эту тему 🙂 .

  • Tazman

    Вот бы еще туториал по созданию странички загрузки файлов с использоанием Аякс и CI 😉

    • Wave

      Да, загрузку файлов аджаксом на CI тоже не прочь был бы увидеть.

      И ещё один то ли совет, то ли просьба по юзабельности сайта.
      Блок: «Вы можете отслеживать обсуждение … или трекбек с Вашего сайта.» — визуально от самих комментариев отделите. Хотя бы чертой hr. Будет лучше восприниматься.

      • Спасибо за совет, попробую изменить.

    • Вообще-то у меня была похожая идея.
      В CI есть библиотека «upload», с которой довольно легко работать. А загрузка с помощью AJAX или без него отличается только тем, что нужно писать JavaScript функцию.
      В общем, я подумаю что включить в эту статью.

    • Я был неправ. В смысле терминологии. Загрузить файл с помощью AJAX нельзя. Но можно реализовать загрузку так, что посетитель не заметит разницу.

      В общем, следующий пост на эту тему 🙂 .

  • Блин, как все не просто. :)Хочу быть кодером.

  • Блин, как все не просто. :)Хочу быть кодером.

  • Спасибо за статью — возможно, пригодится в будущем! А пока что я обходился сторонним сервисом captchator.com, нареканий нет.

  • Спасибо за статью — возможно, пригодится в будущем! А пока что я обходился сторонним сервисом captchator.com, нареканий нет.

  • Pingback: Блог интернет-разработчика » Как на сайте сделать…()

  • Хорошая статья, а главное полезная.

  • Хорошая статья, а главное полезная.

  • Ссылка на пример не рабочая. Поправьте плиз

  • Ссылка на пример не рабочая. Поправьте плиз

  • Dima

    Мне кажется, что хранить данные captcha в БД — это лишняя нагрузка на сервер.

    • Да, вы правы. Но так ими проще управлять.

  • Dima

    Мне кажется, что хранить данные captcha в БД — это лишняя нагрузка на сервер.

    • Да, вы правы. Но так ими проще управлять.

  • Radik

    Заем в БД хранить то просто делаем поле hidden туда помещаем хэш md5 с числом которое написано на картинки потом при вводе просто сравниваем хэши совпал да нет так нет:)

    • Согласен. Честно говоря я уже придумал несколько вариантов улучшения описанного здесь метода (часть решений мне подсказали). Как-нибудь нужно будет отдельный пост написать.

  • Radik

    Заем в БД хранить то просто делаем поле hidden туда помещаем хэш md5 с числом которое написано на картинки потом при вводе просто сравниваем хэши совпал да нет так нет:)

    • Согласен. Честно говоря я уже придумал несколько вариантов улучшения описанного здесь метода (часть решений мне подсказали). Как-нибудь нужно будет отдельный пост написать.

  • Гость

    Статья отстой, ничерта не понятно, где скрипты должны лежать откуда эти скрипты скачать, реализация описана только для винды

    • >> Статья отстой, ничерта не понятно

      Это общая фраза. Если нужен конкретный ответ, задайте вопрос.

      >> где скрипты должны лежать

      Контроллер — в папке application/controllers, библиотека — application/libraries, представление — application/views.
      Эту структуру папок определяет фреймворк CodeIgniter.
      Подробнее почитать можно здесь.

      >> реализация описана только для винды

      Винда тут не причем. На линуксе будет работать точно также. Главное чтобы у вас были установлены Apache, PHP и MySQL.

    • RuSS

      Причем тут винда?

  • Гость

    Статья отстой, ничерта не понятно, где скрипты должны лежать откуда эти скрипты скачать, реализация описана только для винды

    • >> Статья отстой, ничерта не понятно

      Это общая фраза. Если нужен конкретный ответ, задайте вопрос.

      >> где скрипты должны лежать

      Контроллер — в папке application/controllers, библиотека — application/libraries, представление — application/views.
      Эту структуру папок определяет фреймворк CodeIgniter.
      Подробнее почитать можно здесь.

      >> реализация описана только для винды

      Винда тут не причем. На линуксе будет работать точно также. Главное чтобы у вас были установлены Apache, PHP и MySQL.

  • MAD

    некоторая часть пригодиться 🙂 но в базе хранить это точно не пойдет, ждем продолжения

    • Вы правы, есть несколько очень интересных вариантов captcha для которых база не нужна.

  • MAD

    некоторая часть пригодиться 🙂 но в базе хранить это точно не пойдет, ждем продолжения

    • Вы правы, есть несколько очень интересных вариантов captcha для которых база не нужна.

  • А не проше взять капче с joomla v1.5 компонент (com_jcommtnt) — там довольно не плохо реализована капче..

    • Может быть и проще, вообще существует много неплохих библиотек для создания captcha. Но здесь я хотел рассказать именно о библиотеке для CodeIgniter.

  • А не проше взять капче с joomla v1.5 компонент (com_jcommtnt) — там довольно не плохо реализована капче..

    • Может быть и проще, вообще существует много неплохих библиотек для создания captcha. Но здесь я хотел рассказать именно о библиотеке для CodeIgniter.

  • Evgen

    Уважаемый Владимир, выложите пожалуйста на любой файлообменник рабочую сборку формы с каптчей, а то очень сложно новичку сообразить что и куда. Буду очень благодарный.

  • Evgen

    Уважаемый Владимир, выложите пожалуйста на любой файлообменник рабочую сборку формы с каптчей, а то очень сложно новичку сообразить что и куда. Буду очень благодарный.

  • slim

    Ну это тупо бред :). Если бы на сайтах у которых в сутки около 20000 уников прицепить такую чудо капчу :).
    Одного понять не могу. Зачем вообще чет писать в БД и зачем згенериную картинку где то хранить? Она нужна только для того, что бы 1 раз показать пользователю. После этого ее хранение на сервере абсолютно не рационально. А это значит, нахрен она вообще там нада :). Генерим картинку и отдаем браузеру на лету :), сохранять в файл не нуно.
    По поводу того, что для вас использование БД или Сесиий «одинаково», говорит только о том, что вы очень плохо дружите с проектированием и оптимизацией приложений. Оно то одинаково, если на ресурсе больше 200 чел в день не бывает. А када нехилый поток посетителей и нагрузка на сервер не маленькая. То тут за каждый лишний запрос к БД нужно по рукам линейкой бить.
    В приведенном выше алгоритме происходит:
    генерим картинку и сохраняем
    делаем запись в БД
    удаляем картинку
    удаляем запись в БД

    То есть 4 довольно тяжелые для сервера операции, которые включают в себя работу с БД и обращение к файловой системе и запись на ХДД.

    Вместо этого сокращаем до 2:
    Генерим картинку отдаем браузеру
    Инициализируем сесию (не важно какую, в CI можно использовать как стандартные сесии пхп так и встроеные в CI)

    Все, о удалении нам ничего знать больше не нужно ибо у же не наша забота.

    P.S. Перед тем как писать какую то статью не забывайте, что вас будут читать юные начинающие программисты и от вашей статьи в том числе у них будет формироваться стиль программирования. По этому поосторожней 🙂

    • Да, все-таки блоггинг интересное занятие 🙂 Эту статью я написал полтора года назад, а до сих пор комментарии приходят.

      Теперь по теме. В принципе вы правы. Сейчас я бы не стал делать такую captcha, хотя описанный здесь способ приведен в документации к этой библиотеке.
      И хочу отметить, три момента. Первый, сохранение файла действительно выглядит лишней операцией, но если посетитель ошибся при заполнении формы, можно отправить ему тотже файл, а не генерировать его заново. А создание новой картинки тоже достаточно ресурсоемкая операция.
      Второй, PHP сессии по-умолчанию хранятся в файлах, но в принципе можно использовать любой вид хранилища, в т.ч. и БД.
      Третий, удаление устаревших картинок и записей в БД не обязательно будет происходить по одной, т.к. удаляются все записи старше какого-то момента. К тому же эту операцию можно вынести в отдельный скрипт и запускать cron'ом.

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

      P.S. Стиль программирования формируется всю жизнь 🙂 в том числе за счет своих и чужих ошибок 😉

      • slim

        Позвольте опять с Вами не согласиться :).

        Это хорошо, что Вы уже так больше не делаете, значит есть рост :). С чем Вас и поздравляю :).

        Теперь по сути. Хоть как Вы отметили сейчас уже и не делали бы так, выводы которые вы описали в коменте выше, не совсем верны.

        1)»Первый, сохранение файла действительно выглядит лишней операцией, но если посетитель ошибся при заполнении формы, можно отправить ему тотже файл, а не генерировать его заново.»

        Нет Вы не правы, так нельзя делать. Потому, что в таком случаи намного упроститься задача распознавания капчи спам ботам. Если при не правильном вводе, картинка и код не обновляются, можно написать скрипт который будет пытаться распознать изображение с разными настройками до тех пор пока ему это не удастся, ну или банальный полный перебор (хотя это я уже утрирую :)).

        2)Второй, PHP сессии по-умолчанию хранятся в файлах, но в принципе можно использовать любой вид хранилища, в т.ч. и БД.

        Да по умолчанию в файлах. Но на нормальных серверах стоит МекКеш который позволяет хранить в оперативе. Я согласен ПХП сессии тоже не панацея и с ними надо быть поосторожней так как на ресурсах с большой нагрузкой тоже будут проблемы если уж очень активно и там где не нужно их использовать. Но все же это намного оптимальней чем БД. А если использовать сесии Code Igniter которые хранятся на стороне клиента в зашифрованых кукисах проблема вообще решается очень красиво.

        3)Третий, удаление устаревших картинок и записей в БД не обязательно будет происходить по одной, т.к. удаляются все записи старше какого-то момента. К тому же эту операцию можно вынести в отдельный скрипт и запускать cron'ом.

        Если трех колесный волосипед переделать в двухколесный, суть особо не меняеться :). Зачем придумывать жопу, а потом еще делать какие то тело-движения которые грузят сервер, что бы эту жопу почистить :). Тем более пихать это все еще и в кронтаб, что вообще понижает кросплатформеность приложения. Далеко не на всех хостингах Вам удастся запихать задачу в крон.

        Ну по поводу альтернатив капчи :). Чем больше Вы будете усложнять логические примеры, тем больше людей не смогут зарегиться. Так как надо учитывать тот момент, что есть «люди-бараны» :). Которые с капчей с трудом справляються. По поводу нагрузки на сервер не согласен. Совсем даже не уменьшит. За счет чего Вы видите минимизацию нагрузки в таком случаи?

        P.S. Отчасти Вы правы. Учимся все на ошибках. Чужих и своих. Но тут вопрос насколько быстро учимся. Чем больше будет качественных материалов, тем быстрей будем учиться. Если новичку в каждой статье вбивать в голову, что оптимизация очень важный аспект при разработке, тем быстрей он это усвоит и будет пытаться применять это на практике. Пускай в своем пока виденьи далеком от идеала, но все же это уже, что то. Это уже похоже на какой то стиль. Не хочу Вас обидеть. Метериал написан Вами не плох. Но мог бы быть и лучше :). Просто потом приходят на собеседование программеры, которые делают запросы в цыкле и вместо свято уверены, что инфу лучше хранить в текстовых файлах а не в БД :).

        • намного упроститься задача распознавания капчи спам ботам

          Я не совсем согласен. Каждый спам-бот расшифровывает капчу с какой-то вероятностью. Т.е. если он в принципе способен «пробить» каптчу, то с какого-то раза он это сделает. Задача для него усложниться только если новая картинка будет сгенерирована по новому алгоритму (другие шрифты, другой тип деформации и т.п.). Но даже крупные порталы редко такое делают.
          Наверное эта вероятность немного снизится если показывать каждый раз другую картинку.
          Но, на мой взгяд, гораздо эффективнее установить ограничение на количество запросов с одного IP.

          использовать сесии Code Igniter которые хранятся на стороне клиента в зашифрованых кукисах

          Тут у меня вопрос. У Вас есть сведения о том насколько сложно их расшифровать и выполнить подмену данных? Я знаю, что многие считают стандартные сессии CI уязвимыми и существует по крайней мере 7 альтернативных библиотек.

          За счет чего Вы видите минимизацию нагрузки в таком случаи?

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

          Но мог бы быть и лучше

          Тут я должен с Вами согласиться. Может стоит написать новый вариант этой статьи? 🙂

  • slim

    Ну это тупо бред :). Если бы на сайтах у которых в сутки около 20000 уников прицепить такую чудо капчу :).
    Одного понять не могу. Зачем вообще чет писать в БД и зачем згенериную картинку где то хранить? Она нужна только для того, что бы 1 раз показать пользователю. После этого ее хранение на сервере абсолютно не рационально. А это значит, нахрен она вообще там нада :). Генерим картинку и отдаем браузеру на лету :), сохранять в файл не нуно.
    По поводу того, что для вас использование БД или Сесиий «одинаково», говорит только о том, что вы очень плохо дружите с проектированием и оптимизацией приложений. Оно то одинаково, если на ресурсе больше 200 чел в день не бывает. А када нехилый поток посетителей и нагрузка на сервер не маленькая. То тут за каждый лишний запрос к БД нужно по рукам линейкой бить.
    В приведенном выше алгоритме происходит:
    генерим картинку и сохраняем
    делаем запись в БД
    удаляем картинку
    удаляем запись в БД

    То есть 4 довольно тяжелые для сервера операции, которые включают в себя работу с БД и обращение к файловой системе и запись на ХДД.

    Вместо этого сокращаем до 2:
    Генерим картинку отдаем браузеру
    Инициализируем сесию (не важно какую, в CI можно использовать как стандартные сесии пхп так и встроеные в CI)

    Все, о удалении нам ничего знать больше не нужно ибо у же не наша забота.

    P.S. Перед тем как писать какую то статью не забывайте, что вас будут читать юные начинающие программисты и от вашей статьи в том числе у них будет формироваться стиль программирования. По этому поосторожней 🙂

    • Да, все-таки блоггинг интересное занятие 🙂 Эту статью я написал полтора года назад, а до сих пор комментарии приходят.

      Теперь по теме. В принципе вы правы. Сейчас я бы не стал делать такую captcha, хотя описанный здесь способ приведен в документации к этой библиотеке.
      И хочу отметить, три момента. Первый, сохранение файла действительно выглядит лишней операцией, но если посетитель ошибся при заполнении формы, можно отправить ему тотже файл, а не генерировать его заново. А создание новой картинки тоже достаточно ресурсоемкая операция.
      Второй, PHP сессии по-умолчанию хранятся в файлах, но в принципе можно использовать любой вид хранилища, в т.ч. и БД.
      Третий, удаление устаревших картинок и записей в БД не обязательно будет происходить по одной, т.к. удаляются все записи старше какого-то момента. К тому же эту операцию можно вынести в отдельный скрипт и запускать cron'ом.

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

      P.S. Стиль программирования формируется всю жизнь 🙂 в том числе за счет своих и чужих ошибок 😉

      • slim

        Позвольте опять с Вами не согласиться :).

        Это хорошо, что Вы уже так больше не делаете, значит есть рост :). С чем Вас и поздравляю :).

        Теперь по сути. Хоть как Вы отметили сейчас уже и не делали бы так, выводы которые вы описали в коменте выше, не совсем верны.

        1)»Первый, сохранение файла действительно выглядит лишней операцией, но если посетитель ошибся при заполнении формы, можно отправить ему тотже файл, а не генерировать его заново.»

        Нет Вы не правы, так нельзя делать. Потому, что в таком случаи намного упроститься задача распознавания капчи спам ботам. Если при не правильном вводе, картинка и код не обновляются, можно написать скрипт который будет пытаться распознать изображение с разными настройками до тех пор пока ему это не удастся, ну или банальный полный перебор (хотя это я уже утрирую :)).

        2)Второй, PHP сессии по-умолчанию хранятся в файлах, но в принципе можно использовать любой вид хранилища, в т.ч. и БД.

        Да по умолчанию в файлах. Но на нормальных серверах стоит МекКеш который позволяет хранить в оперативе. Я согласен ПХП сессии тоже не панацея и с ними надо быть поосторожней так как на ресурсах с большой нагрузкой тоже будут проблемы если уж очень активно и там где не нужно их использовать. Но все же это намного оптимальней чем БД. А если использовать сесии Code Igniter которые хранятся на стороне клиента в зашифрованых кукисах проблема вообще решается очень красиво.

        3)Третий, удаление устаревших картинок и записей в БД не обязательно будет происходить по одной, т.к. удаляются все записи старше какого-то момента. К тому же эту операцию можно вынести в отдельный скрипт и запускать cron'ом.

        Если трех колесный волосипед переделать в двухколесный, суть особо не меняеться :). Зачем придумывать жопу, а потом еще делать какие то тело-движения которые грузят сервер, что бы эту жопу почистить :). Тем более пихать это все еще и в кронтаб, что вообще понижает кросплатформеность приложения. Далеко не на всех хостингах Вам удастся запихать задачу в крон.

        Ну по поводу альтернатив капчи :). Чем больше Вы будете усложнять логические примеры, тем больше людей не смогут зарегиться. Так как надо учитывать тот момент, что есть «люди-бараны» :). Которые с капчей с трудом справляються. По поводу нагрузки на сервер не согласен. Совсем даже не уменьшит. За счет чего Вы видите минимизацию нагрузки в таком случаи?

        P.S. Отчасти Вы правы. Учимся все на ошибках. Чужих и своих. Но тут вопрос насколько быстро учимся. Чем больше будет качественных материалов, тем быстрей будем учиться. Если новичку в каждой статье вбивать в голову, что оптимизация очень важный аспект при разработке, тем быстрей он это усвоит и будет пытаться применять это на практике. Пускай в своем пока виденьи далеком от идеала, но все же это уже, что то. Это уже похоже на какой то стиль. Не хочу Вас обидеть. Метериал написан Вами не плох. Но мог бы быть и лучше :). Просто потом приходят на собеседование программеры, которые делают запросы в цыкле и вместо свято уверены, что инфу лучше хранить в текстовых файлах а не в БД :).

        • намного упроститься задача распознавания капчи спам ботам

          Я не совсем согласен. Каждый спам-бот расшифровывает капчу с какой-то вероятностью. Т.е. если он в принципе способен «пробить» каптчу, то с какого-то раза он это сделает. Задача для него усложниться только если новая картинка будет сгенерирована по новому алгоритму (другие шрифты, другой тип деформации и т.п.). Но даже крупные порталы редко такое делают.
          Наверное эта вероятность немного снизится если показывать каждый раз другую картинку.
          Но, на мой взгяд, гораздо эффективнее установить ограничение на количество запросов с одного IP.

          использовать сесии Code Igniter которые хранятся на стороне клиента в зашифрованых кукисах

          Тут у меня вопрос. У Вас есть сведения о том насколько сложно их расшифровать и выполнить подмену данных? Я знаю, что многие считают стандартные сессии CI уязвимыми и существует по крайней мере 7 альтернативных библиотек.

          За счет чего Вы видите минимизацию нагрузки в таком случаи?

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

          Но мог бы быть и лучше

          Тут я должен с Вами согласиться. Может стоит написать новый вариант этой статьи? 🙂

  • Alexx

    А я вот у себя убрал логические примеры, поставил опять рандом. Всё просто — сколько этих примеров вы сможете записать в массив ? Врядли 4!(4-факториал). А перебор — это и не такое уж утрирование иногда…

    • Такой перебор — это индивидуальная работа (спамера). А он будет этим заниматься только для очень «перспективного» ресурса. Поэтому для большинства сайтов простейшая чуть-чуть не стандартная captcha фильтрует ~90% спама.

  • Alexx

    А я вот у себя убрал логические примеры, поставил опять рандом. Всё просто — сколько этих примеров вы сможете записать в массив ? Врядли 4!(4-факториал). А перебор — это и не такое уж утрирование иногда…

    • Такой перебор — это индивидуальная работа (спамера). А он будет этим заниматься только для очень «перспективного» ресурса. Поэтому для большинства сайтов простейшая чуть-чуть не стандартная captcha фильтрует ~90% спама.

  • D@RK_DIE$EL

    Спасибо, все получилось.
    Использовал вместо библиотеки плагин, немного пришлось переделать вызов и что-то встроенный шрифт не работает, пишет что это не шрифт.

    Такая проблема в строке $exp = time() – 7200; выдает ошибку

    Parse error: syntax error, unexpected T_STRING in D:WEBlocalhostLamsystemapplicationcontrollersregistration.php on line 119

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

    • Я не могу определить почему у вас возникла эта ошибка.
      $exp = time() – 7200; записано правильно.
      Проверьте соседние строки.

      • D@RK_DIE$EL

        Все сделал, не знаю что это было, соседние строки были в порядке. Все навсего удалил «-» и снова поставил и все заработало.

  • D@RK_DIE$EL

    Спасибо, все получилось.
    Использовал вместо библиотеки плагин, немного пришлось переделать вызов и что-то встроенный шрифт не работает, пишет что это не шрифт.

    Такая проблема в строке $exp = time() – 7200; выдает ошибку

    Parse error: syntax error, unexpected T_STRING in D:\WEB\localhost\Lam\system\application\controllers\registration.php on line 119

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

    • Я не могу определить почему у вас возникла эта ошибка.
      $exp = time() – 7200; записано правильно.
      Проверьте соседние строки.

      • D@RK_DIE$EL

        Все сделал, не знаю что это было, соседние строки были в порядке. Все навсего удалил «-» и снова поставил и все заработало.

  • В принципе тут не хватает только одного- кеширования капчи!
    т.е.каждый раз когда нам нужна капча мы смотри время создания предыдущей, и если её время создания отличается от времени текущего запроса меньше чем на 1 секунду, показываем её, иначе генерируем новую.
    Если этого не делать, сервер может просто лечь от примитивного ддоса на генерацию капчи. так что стоит развить пример дальше, всё необходимое уже есть =)
    Да и кстати если пойти ещё дальше, генерировать капчу можно только по требованию пользователя обновить её, а не при обновлении страницы =) таким образом везде,Ю где нужна будет капча пользователю не придётся распознавать новую, ну а тупые боты всё равно будут её заново распознавать, умные будут конечно сравнивать с предыдущей, но если ещё развивать тему дальше можно и тут выкрутиться не доставив неудобства юзверю=)

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

      • Не уверен, насчет стойкости такой капчи. Во всяком случае, если используется одна картинка.
        Серверу будет отправлен угол поворота, т.е. число. Если сделать маленький шаг поворота (например, +/-1 градус), то будет большое количество ошибок у посетителей. Если увеличить шаг поворота, то уменьшается число возможных комбинаций. Например, шаг 10 градусов, количество вариантов — 36.
        Т.е. из сотни спамерских запросов, штуки три пройдут только благодаря теории вероятности.
        Текстовая капча из четырех символов обеспечивает 1679616 комбинаций (36^4, из расчета 26 букв, 10 цифр).

        Я видел поворачивающуюся капчу на каком-то сайте, но там использовались одновременно 3 картинки.

        С другой стороны, такая капча практически не нагружает сервер, и это большой плюс.

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

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

  • В принципе тут не хватает только одного- кеширования капчи!
    т.е.каждый раз когда нам нужна капча мы смотри время создания предыдущей, и если её время создания отличается от времени текущего запроса меньше чем на 1 секунду, показываем её, иначе генерируем новую.
    Если этого не делать, сервер может просто лечь от примитивного ддоса на генерацию капчи. так что стоит развить пример дальше, всё необходимое уже есть =)
    Да и кстати если пойти ещё дальше, генерировать капчу можно только по требованию пользователя обновить её, а не при обновлении страницы =) таким образом везде,Ю где нужна будет капча пользователю не придётся распознавать новую, ну а тупые боты всё равно будут её заново распознавать, умные будут конечно сравнивать с предыдущей, но если ещё развивать тему дальше можно и тут выкрутиться не доставив неудобства юзверю=)

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

      • Не уверен, насчет стойкости такой капчи. Во всяком случае, если используется одна картинка.
        Серверу будет отправлен угол поворота, т.е. число. Если сделать маленький шаг поворота (например, +/-1 градус), то будет большое количество ошибок у посетителей. Если увеличить шаг поворота, то уменьшается число возможных комбинаций. Например, шаг 10 градусов, количество вариантов — 36.
        Т.е. из сотни спамерских запросов, штуки три пройдут только благодаря теории вероятности.
        Текстовая капча из четырех символов обеспечивает 1679616 комбинаций (36^4, из расчета 26 букв, 10 цифр).

        Я видел поворачивающуюся капчу на каком-то сайте, но там использовались одновременно 3 картинки.

        С другой стороны, такая капча практически не нагружает сервер, и это большой плюс.

  • Pingback: Руководства, статьи и заметки()

  • San

    Спасибо!

  • DiscUs

    Спасибо!

  • Shnw1

    Здравствйте!
    Ссылка на собранную каптчу не работает. Можно перезалить?

    • Если не ошибаюсь, этой ссылки вообще в статье не было 🙂
      Но уже добавил — пробуйте.
      Не забудьте изменить настройки в конфигурационных файлах.

  • 343

    капча с базой данныйх — фигня

  • Tolxy Vx8 Ru

    tolxy chat чат бесплатные знакомства и общение онлайн игры музыка развлечения http://tolxy.vx8.ru

  • Здравствуйте, ничего удивительного в том, что тема жива и актуальна нет, спам изрядно достает практически всех. Если возможно, пожалуйста еще раз выложите пример, к величайшему сожалению ссылка на upload.com.ua умерла — файл не найден.
    Спасибо.

  • Я не выкладывал пример на upload.com.ua.
    Актуальная ссылка в конце статьи (кнопка «Скачать»).