Безопасные формы на PHP


Alatartsev (IDE) Sergey

Структура обработки введенных в форму данных

Иногда нам приходиться писать различные модули для общения с посетителем сайта. Это может быть форум, гостевая книга или форма для отправки e-mail. Одной из основополагающей части этих программ являются поля для получения информации от пользователя, так называемые формы. Пользователь заполняет их и тем самым информация передается администраторам или всем посетителям, в зависимости от обработчика. Большинство людей не имеют зловредных целей, но порой попадаются юзеры с плохими намерениями. Они стремятся использовать вредоносные теги, спамить и флудить, администраторы же стремятся свести риск повреждения своей программы к нулю. Есть множество способов сделать это, я попробую рассказать лишь об основных. Все дело в Обработчике, именно он является главной частью нашей программы, в него поступают все сведения, и его задачей является отделить нужное от не нужного, полезное от без полезного. В данных примерах будет использоваться язык сетевого программирования PHP.

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

<input type=text name=name maxlength=10>

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

$name=substr($name,0,10);

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

$name=htmlspecialchars($name);

В этой строчке мы видим, что htmlspecialchars( ) попросту убирает теги. Хм.. А что если администратору хочется писать жирным или курсивом? Ответ прост:

$text = str_replace ("[b]", "<b>", $text);
$text = str_replace ("[/b]", "</b>", $text);

Мы заменим привычный нам тег <b></b> на [b][/b]. То есть мы будем писать в сообщении вместо обычных тегов, новые. Обработчик будет отслеживать новые и менять на старые =). Кстати, с помощью str_replace можно заменять смайлики вида "=)" на картинку:

$text = str_replace (":0", "<img src=\"smile.gif\">", $text);

Немного отвлеклись. Всегда нужно быть осторожными и продумывать шаги. Поля такие как: имя, город, e-mail и т.д. являются однострочными, следовательно, переход на новую строку должен пресекаться.

$name=ereg_replace("\n"," ", $name);
$mail=ereg_replace("\n"," ", $mail);
$gorod=ereg_replace("\n"," ", $gorod);

Знак \n - означает переход на новую строку, он заменяется на пробел. Для того, что бы проверить, что переход на новую строку состоит из двух символов, создайте пустой текстовый файл и просто стукните enter. Вы перейдете на новую строку. Не делая никаких изменений после, просто закройте редактор, предварительно сохранившись. Посмотрите свойства только что созданного файла. Объем будет составлять два байта, то есть два символа.

Следующей проблемой, являются незаполненные поля, а что если они очень важны? Заполнение формы будет напрасным. Выход вот:

if ($name= =' ')
{ echo "<center> <b>Не могу добавить сообщение - Вы не ввели имя!</b></center>";
exit; }

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

if (empty($name)) {
echo "Пустое имя!";
exit;
}

Смысл один и тот же у последних двух примеров, только разве что информационное сообщение другое =). Многие пользователи так и норовят понатыкать везде непонятных закорючек - &^*"][. Если к тому же мы используем mySQL то такой язык юзера может привести к ошибке. Лекарство:

if (preg_match("/[^(\w)|(\x7F-\xFF)|(\s)]/",$name)) {
echo "Неправильное имя!";
exit;
}

Но учтите, что нужно разрешить использование "собаки" при вводе в поле e-mail, иначе получиться не вполне корректно:

if (preg_match("/[^(\w)|(\@)|(\.)]/",$mail)) {
echo "Неправильный электронный адрес!";
exit;
}

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

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

15.06.04

читать еще в разделе