Безопасность в среде Интернет включает в себя много различных аспектов, таких как система защиты веб-сервера, безопасность баз данных, проверка данных, вводимых пользователем, приемы и методы шифрования и др.
Проверке корректности данных, вводимых посетителем, необходимо уделять особое внимание. Любая информация, отправляемая с клиентской машины, может быть подвергнута фальсификации и содержать заведомо ложную информацию, но и зловредный код.
HTML-формы отсылают обработчику данные либо методом GET, либо методом POST, в зависимости от того, какое значение принимает атрибут method тега <form>. Интерпретатор РНР помещает значения полей HTML-формы соответственно либо в массив $_GET, либо массив $_POST.
Пусть имеется HTML-форма, которая имеет два текстовых поля для имени пользователя name и его электронного адреса email, размещаемая в файле 419.php.
Файл 419.php
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=windows-1251">
<title>Файл 419.php</title>
</head>
<body>
<form action="420.php" method="post">
Имя: <input name="name" type="text" size="25">
E-mail: <input name="email" type="text" size="25">
<input name="" type="submit" value="Отправить">
</form>
</body>
</html>
Как видно из скрипта, помимо текстовых полей HTML-форма содержит кнопку типа submit, нажатие на которую приводит к отправке данных обработчику 420.php. Так как данные отправляются обработчику методом POST, то получить содержимое текстовых полей name и email в файле 420.php можно, обратившись к соответствующим элементам суперглобального массива $_POST['name'] и $_POST['email'].
Проверить, заполнены текстовые поля или нет, РНР позволяет при помощи одной из двух функций: empty() и isset(). Функция empty() возвращает true, если переменная не существует или пустая, в противном случае возвращает false. Конструкция isset() возвращает true, если переменная существует, и false — в противном случае.
Таким образом, если текстовое поле name является обязательным для заполнения, то следует проверить, содержит ли оно какие-либо символы при помощи функции empty().
Файл 420.php
<?php
//Выставляем уровень обработки ошибок
error_reporting(E_ALL & ~E_NOTICE);
//Проверяем, передано ли значение поля name
if(empty($_POST['name']))
{
//Если переменная $name не установлена, просим повторить ввод имени
echo "Не введено обязательное для заполнения поле name<br>";
echo "<a href=# onClick='history.back()'>Вернуться к правке </a>";
exit();
}
//Производим обработку данных HTML-формы
echo "Имя - $_POST[name] <br>";
echo "E-mail - $_POST[email]";
?
Если элемент суперглобального массива $_POST['name'] пуст, следовательно, обязательное поле name не было заполнено, что приводит к выводу в окно браузера предупреждения и ссылки возврата, реализованной при помощи функции JavaScript history.back().
Запретить пользователю ввод пробельного символа можно, пропустив значение элемента суперглобального массива $_POST['name'] через функцию trim(), которая удаляет из строки начальные и завершающие пробельные символы.
Другой вариант файла 420.php
<?php
//Выставляем уровень обработки ошибок
error_reporting(E_ALL & ~E_NOTICE);
//Удаляем пробельные символы в начале и в конце строки
$_POST['name']=trim($_POST['name']);
//Проверяем, передано ли значение поля name
if(empty($_POST['name']))
{
//Если переменная $name не установлена, просим повторить ввод имени
echo "Не введено обязательное для заполнения поле name<br>";
echo "<a href=# onClick='history.back()'>Вернуться к правке </a>";
exit();
}
//Производим обработку данных HTML-формы
echo "Имя - $_POST[name] <br>";
echo "E-mail - $_POST[email]";
?>
В окне веб-браузера это будет выглядеть ТАК.
Конструкция isset() позволяет проверить, существует ли переменная или элемент массива вообще. Она не может использоваться в предыдущих примерах, т.к. переменная даже со значением пустой строки считается существующей. Использование конструкции isset() больше подходит для обработки флажков: элемент суперглобального массива для флажка (checkbox) устанавливается только в том слечае, если флажок отмечен, в противном случае элемент для флажка в суперглобальном массиве не создается. Рассмотрим пример HTML-формы, которая содержит два флажка (checkbox), значение которых проверяется в обработчике при помощи констукции isset().
Примечание. Следует обратить внимание на то, что в отличие от HTML-формы, рассмотренной в предыдущем примере, данная HTML-форма и ее обработчик находятся в одном файле. Обработчик вступает в действие только тогда, когда суперглобальный массив $_POST содержит хотя бы один элемент. Последнее проверяется при помощи функции empty().
Использование конструкции isset()
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=windows-1251">
<title>Использование конструкции isset()</title>
</head>
<body>
<?php
//Выставляем уровень обработки ошибок
error_reporting(E_ALL & ~E_NOTICE);
$ch1=$ch2="";
if(isset($_POST['ch1']))
{
echo "Первый флажок отмечен <br>";
$ch1="checked";
}
if(isset($_POST['ch2']))
{
echo "Второй флажок отмечен <br>";
$ch2="checked";
}
?>
<form action="" method="post">
<input name="ch1" type="checkbox" value="<?=$ch1;?>">первый флажок<br>
<input name="ch2" type="checkbox" value="<?=$ch2;?>">второй флажок<br>
<input name="" type="submit" value="Отправить">
</form>
</body>
</html>
В окне веб-браузера это будет выглядеть ТАК.
Впрочем в этом примере вместо конструкции isset() вполне можно использовать функцию empty().
Проверка корректности ввода чисел является важной задачей. Часто веб-разработчики полагают, что в HTML-формы, предназначенные для ввода чисел, пользователи не могут вводит ничего. Однако вместо чисел может быть введен текст и целые мини программы деструктивного действия, приводящие в лучшем случае к сбою работы скрипта, а в худшем — к взлому.
Если поле предназначено для ввода только целых чисел, то самым простым способом обезопасить скрипт является обработка вводимого значения при помощи стандартной функции intval(), которая приводит любой аргумент к целому числу (или к 0, если это невозможно).
Использование функции intval()
<?php
//Приводим POST-параметр number к целому числу
$_POST['number']=intval($_POST['namber']);
?>
Однако приведение параметра к целому типу не всегда приемлемо — зачастую требуется указать пользователю на ошибку. Для этого удобно воспользоваться регулярными выражениями.
Для проверки целых чисел в регулярных выражениях введен специальный класс \d. Кроме этого, необходимо явноуказать начало (^) и конец строки ($), иначе выражение будет срабатывать лишь на одну цифру, помимо которой в строку можно будет поместить все, что угодно — регулярное выражение найдет цифру и проигнорирует все остальное. Привязка к началу и концу строки позволяет избежатьэтого:
"|^[\d]*$|"
Обработка чисел с плавающей точкой состоит из нескольких частей. Целой части числа соответствует выражение [\d]*. После точки, которую необходимо экранизировать, следует дробная часть, также описываемая выражением [\d]*. Теперь объединяя фрагменты, мы можем получить шаблон для чисел с плавающей тоской — "|^[\d]*\.[\d]*S|". Завершающим штрихом будет учет разного формата разделителя целой и дробной части, в качестве которого может выступать как точка (23.12), так и запятая (23,12) — для учета чисел в обоих форматах регулярное выражение следует изменить следующим образом: "|^[\d]*[\.,][\d]*$|". Однако такое выражение не позволит вводить целые числа, которые являются частным случаем чмсел с плавающей точкой. Чтобы это исправить, необходимо добавить символ ? после класса [\.,].
"|^[\d]*[\.,]?[\d]*$|"
Рассмотрим пример HTML-формы, принимающей цену price и количество товара number. Поле price принимает числа с плавающей точкой, а поле number — целые значения.
Проверка чисел на корректность
<html>
<head>
<meta http-equiv="Content-Type" content="text/html;
charset=windows-1251">
<title>Проверка чисел на корректность</title>
</head>
<body>
<form action="" method="post">
Количество <input name="number" type="text"
value="<?=$_POST['number'];?>" size="60">
<br>
Цена <input name="price" type="text"
value="<?=$_POST['price'];?>" size="60">
<br>
<input name="" type="submit" value="Проверить">
</form>
<?php
//Обработчик HTML-формы
if(!empty($_POST))
{
if(!preg_match("|^[\d]*$|", $_POST['number']))
{
exit ("Не верен формат количества товара");
}
if(!preg_match("|^[\d]*[\.,]?[\d]*$|",$_POST['price']))
{
exit ("Не верен формат цены ");
}
echo number_format($_POST['number']*$_POST['price'], 2, '.', '');
}
?>
</body>
</html>
В окне веб-браузера это будет выглядеть ТАК.
Проверку правильности заполнения адреса электронной почты, также удобно реализовать при помощи регулярных выражений. Будем исходить из того, что адрес должен иметь вид [email protected]. У адреса есть две составляющие: имя пользователя и имя домена, которые разделены знаком @. В имени пользователя могут присутствовать буквы нижнего и верхнего регистров латинского алфавита, цифры, знаки подчеркивания, минуса и точки. В качестве разделителя между именем пользователя и именем домена в выражении требуется добавить знак @, после чего следует доменное имя, которое тоже может состоять из букв нижнего и верхнего регистра латинского алфавита, цифр, знаков препинания, тире и точки. Итак, регулярное выражение, проверяющее имя пользователя, наличие разделителя и доменного имени, выглядит следующим образом:
"[-0-9a-z_]+@[-0-9a-z^\.]+"
Для проверки доменного имени первого уровня (.ru, .com) необходимо добавить следующеевыражение:
"\.[a-z]{2, 6}"
Примечание. Домены первого уровня могут содержать до 6 символов (например, travel). Причем символ подчеркивания в доменном имени встречаться не может.
Символ "." в регулярных выражениях используется для обозначения любого символа, поэтому для поиска соответствия точки в регулярном выражении этот символ экранируется обратным слэшем: "\.".
Объединяя эти строки, можно получить следующее регулярное выражение в формате Perl для проверки корректности адресов электронной почты:
"[-0-9a-z_] + @ [-0-9a-z^\.]+\.[a-z]{2, 6} | i"
Примечание. Модификатор i в регулярном выражении сообщает интерпретатору, чтобы поиск соответствия производился без учета регистра. Пробелов между символами в регулярном выражении не должно быть.
Этому регулярному выражению будет соответствовать e-mail, однако если строка будет содержать адрес электронной почты и ничего более, то регулярное выражение необходимо срабдить привязкой к началу (^) и концу текста ($):
"| ^ [-0-9a-z_] + @ [-0-9a-z^\.]+\.[a-z]{2, 6} $ | i"
Проверка корректности адреса электронной почты
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=windows-1251">
<title>Проверка корректности адреса электронной почты</title>
</head>
<body>
<form action="" method="post">
<input name="name" type="text" value="<?=$_POST['name'];?>" size="35">
<input name="" type="submit" value="Проверить">
</form>
<?php
//Обработчик HTML-формы
if(isset($_POST['name']))
{
if(preg_match("|^[-0-9a-z_]+@[-0-9a-z^\.]+\.[a-z]{2,6}$|i", $_POST['name']))
{
echo "e-mail верен";
}
else
{
echo "e-mail не верен";
}
}
?>
</body>
</html>
В окне веб-браузера это будет выглядеть ТАК.