Следующая статья: Какие типы есть в PHP?
Защита сайта от спамеров с использованием PHP
В настоящее время множество хороших сайтов страдает от огромного потока рекламных объявлений или просто спама, который не добросовестные пользователи интернета пытаются расположить везде, где только это возможно: в гостевых книгах, форумах, каталогах и везде, где только можно оставить пару строк своего текста.
Основным методом борьбы с явлением такого вида спама является создание всевозможных проверок на человечность, то есть, определения, кто вводил данные в форму, человек или программа. К таким проверкам можно отнести:
- просьбу ввести в текстовое поле номер или слово с картинки
- ввести ответ на загадку или какой-либо вопрос
- нажать одну из нескольких кнопок (<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']='font_name.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(). И в заключении примерная схема реализации:
<form name="codegen"> <p><img src="my_codegen.php" alt="" /></p> <p><input type="text" name="code"></p> <p><input type="submit" name="send"></p> </form>
<?php
function generate_code()
{
…
}
function chec_code($code)
{
…
}
if (isset($_GET['code']))
{ echo 'Введенный код: '. $_GET['code'];
if (chec_code($_GET['code']))
{ echo '<br />Верный код подтверждения!';
}
else
{ echo '<br />Неверный код подтверждения!';
}
}
?>