Web - Защита сайта от спамеров с использованием PHP. Практическое применение кода подтверждения с картинки - PRCY⮭net
В настоящее время множество хороших сайтов страдает от огромного потока рекламных объявлений или просто спама, который не добросовестные пользователи интернета пытаются расположить везде, где только это возможно: в гостевых книгах, форумах, каталогах и везде, где только можно оставить пару строк своего текста.

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

* просьбу ввести в текстовое поле номер или слово с картинки
* ввести ответ на загадку или какой-либо вопрос
* нажать одну из нескольких кнопок (<input type="button">)
* выбрать один из нескольких правильных ответов (<input type="radio">)
* выбрать несколько ответов (<input type="checkbox">)
* …

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

Алгоритм сверки данных в этом случае осуществляется несколькими способами:

# В форме находится один и более скрытых элементов (<input type="hidden">) содержащих какие-либо значения и поле для ввода данных.
# Генерируемое случайным образом значение сохраняется в БД и имеет небольшой срок жизни, при совпадении со значением из текстового поля находящегося. в форме эта запись удаляется.
# Использование Cookies, т.е. сохранение правильного ответа у пользователя (крайне не удобно и не всегда работает).
# В качестве кода подтверждения используются перемешанные числа текущей даты.
# Предыдущий вариант, но разбавленный латинскими буквами.
# Фантазия разработчиков безгранична…

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

И так, начнем писать наш php-код, а то я уж слишком сильно углубился в теоретическую часть вопроса. Создаем новый php-файл и для начала напишем в нем функцию, которая будет "придумывать" код подтверждения из текущей даты, выглядеть она будет примерно так:

function generate_code()
{
$week_day = date("w"); // день недели
$day = date("d"); // число
$hours = date("H"); // час
$minuts = substr(date("H"), 0 , 1); // минуты (первая цифра)
$mouns = date("m"); // месяц
$year_day = date("z"); // день в году

$str = $week_day . $day . $hours . $minuts . $mouns . $year_day; // формируем результирующую строку

$array_mix = preg_split('//', $str, -1, PREG_SPLIT_NO_EMPTY); // разбиваем сроку на символы и заносим их в массив
srand ((float)microtime()*1000000); // запускаем генератор случейных чисел
shuffle ($array_mix); // перемешиваем значения в массиве
return implode("", $array_mix); // объединяем все значения массива в строку и возвращаем
}

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

function img_code()
{
// что бы не кэшировалась картинка
header("Expires: Mon, 26 Jul 1997 05:00:00 GMT"); // дата в прошлом
header("Last-Modified: " . gmdate("D, d M Y H:i:s", 10000) . " GMT"); // 1 января 1970
header("Cache-Control: no-store, no-cache, must-revalidate"); // HTTP/1.1
header("Cache-Control: post-check=0, pre-check=0", false); // еще раз, для надежности
header("Pragma: no-cache"); // HTTP/1.0
header("Content-Type:image/png");

$linenum = 2; // Число линий (для шума в картинке)
$img_arr = array( // массив с именами файлов-фонов
"codegen.png",
"codegen0.png"
);
$font_arr = array(); // массив со шрифтами
$font_arr[0]["fname"] = "04B_24__.TTF";
$font_arr[0]["size"] = 15;
$font_arr[1]["fname"] = "Kiloton.ttf";
$font_arr[1]["size"] = 9;

$n = rand(0,sizeof($font_arr)-1); // выбираем шрифт
$img_fn = $img_arr[rand(0, sizeof($img_arr)-1)]; // выбираем фон

$im = imagecreatefrompng (code_dir . $img_fn); // загружаем фон

for ($i=0; $i<$linenum; $i++) // шум в виде линий
{
$color = imagecolorallocate($im, rand(0, 255), rand(0, 200), rand(0, 255));
imageline($im, rand(0, 20), rand(1, 50), rand(150, 180), rand(1, 50), $color);
}

$color = imagecolorallocate($im, rand(0, 200), 0, rand(0, 200)); // цвет текста
imagettftext ($im, $font_arr[$n]["size"], rand(-4, 4), rand(10, 45), rand(20, 35), $color, code_dir.$font_arr[$n]["fname"], generate_code()); //сам текст в пределах картинки

for ($i=0; $i<$linenum; $i++) // шум в виде линий
{
$color = imagecolorallocate($im, rand(0, 255), rand(0, 200), rand(0, 255));
imageline($im, rand(0, 20), rand(1, 50), rand(150, 180), rand(1, 50), $color);
}

ImagePNG ($im); // вывод изображения
ImageDestroy ($im); // Освобождаем память
}

Для того, что бы все работало, в начале php-скрипта пишем:

define("code_dir", "my_codegen/");


, а в конце

img_code();

Затем создаете папку my_codegen в той директории, в которой расположен php-скрипт – генератор изображений с кодом подтверждения, и создаете codegen.png и codegen0.png в Photoshope или другом графическом редакторе, копируете туда шрифты TrueType с именами Kiloton.ttf и 04B_24__.TTF. Все на этом генератор картинок завершен.

Теперь нам нужна функция для проверки введенных данных, она будет реализована по тому же принципу что и generate_code, ее нужно поместить в отдельный php-скрипт, который будет осуществлять проверку введенных данных:

function chec_code($code)
{
$code = trim($code);

$array_mix = preg_split ('//', generate_code(), -1, PREG_SPLIT_NO_EMPTY);
$m_code = preg_split ('//', $code, -1, PREG_SPLIT_NO_EMPTY);

$result = array_intersect ($array_mix, $m_code);

if (sizeof($result) == sizeof($array_mix))
{
return TRUE;
}
else
{
return FALSE;
}
}

В этот же файл, в конец добавьте функцию generate_code()

И в заключении примерная схема реализации:

<?php
echo<<<END
<form name="codegen">
<p><img src="my_codegen.php" border="0"></p>
<p><input type="text" name="code"></p>
<p><input type="submit" name="send"></p>
</form>
END;

function generate_code()
{

}

function chec_code($code)
{

}

if (isset($_GET['code']))
{
echo "Введенный код: " . $_GET['code'];
if (chec_code($_GET['code']))
{
echo "<br>Верный код подтверждения!!!";
}
else
{
echo "<br>Неверный код подтверждения!!!";
}
}
?>
Information
  • Posted on 27.04.2013 14:17
  • Просмотры: 1132