PHP Фильтрация входных данных в PHP

Фильтрация входных данных — одна из самых важных вещей, которой надо уделять внимание при разработке веб-сайта. Опытным программистам это известно, а новички пусть запомнят одну очень важную вещь:

Данным, полученным от пользователя, доверять нельзя.

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

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

Введение

Как было отмечено выше, начиная с версии 5.2.0 в PHP присутствуют специальные функции для фильтрации данных. Одна из таких функций - filter_var. Сначала нам необходимо убедиться, что нужные нам функции установлены и доступны. Для этого напишем простенький скрипт:
if (function_exists('filter_list'))
{
  echo 'список фильтров установлен!';
} else {
  die('Ошибка: фильтры не найдены.');
}
Если все в порядке и функции фильтров установлены, давайте продолжим. Взглянем на список установленных фильтров. Получить список фильтров можно уже известной нам функцией filter_list:
echo "
    \n"; $filters = filter_list(); foreach ($filters as $filter) { echo "
  • ".$filter."
  • \n"; } echo "
\n";
В результате выполнения этой программы мы получим список фильтров, которыми можем пользоваться.

Три способа фильтрации данных

Существует три основных способа фильтрации входных данных:

  • Validate (проверка) — позволяет проверить и убедиться в том, что введенные данные действительно являются тем, что ожидается. Флаги проверки имеют префикс FILTER_VALIDATE_
  • Sanitize (очистка) — “Очищает” входящие данные. Убирает, экранирует или кодирует недозволенные символы. Флаги очистки начинаются с FILTER_SANITIZE_
  • Flags (флаги) — с помощью флагов вы можете задавать различные варианты поведения фильтров. Флаги бывают как общими для всех фильтров, так и специфические флаги для конкретных фильтров. Обычно они начинаются с FILTER_FLAG_

filter_var($var, FLAG[, FLAGS])

Функция filter_var() принимает как минимум два параметра — имя переменной, которую вы собираетесь фильтровать и флаг. Давайте начнем с примера, который очень часто требуется: валидация (проверка) корректности e-mail адреса. Для этого мы будем использовать функцию filter_var() и флаг FILTER_VALIDATE_EMAIL.
$email = 'fgdjkdgdfghdsdfj';
$valid_email = filter_var($email, FILTER_VALIDATE_EMAIL);
Результат работы этой функции имеет логический тип(bool) и принимает значение true если строка успешно прошла через фильтр, и false в обратном случае:
if ($valid_email !== false)
{
  echo "E-mail адрес корректный";
} else {
  echo "Некорректный E-mail адрес";
}
Так как fgdjkdgdfghdsdfj — это, конечно же, некорректный e-mail адрес, то фильтр вернет false. Все очень просто, не так ли? Всего лишь вызов одной функции вместо громоздкого регулярного выражения.

Константы фильтров (флаги)

Давайте для примера создадим несколько различных переменных, на которых и будем демонстрировать наши фильтры.
$int = 432;
$bool = true;
$float = 432.43;
$reg = "/^([a-zA-Z0-9 ]){4,16}$/";
$url = "http://devolio.com/blog";
$email = 'joey@devolio.com';
$ipaddr = '127.0.0.1';
$ipres = "192.168.0.*";
$ipv6addr = "2001:0db8:85a3:08d3:1319:8a2e:0370:7334";
$string = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234 567890`~!@#$%^&*()-_=+[{]};:'\"<,>.?/|\\n\\r\\t";
$int_octal = decoct(800.82);
$int_hex = dechex(800.82);
Также обратите внимание, что переменная $string содержит символы табуляции и переносы строк, для того чтобы лучше было видно что именно фильтруется.

Ниже представлены константы фильтров, которые мы будем использовть. Кстати говоря, это не все фильтры, которые существуют.

Проверка типа переменной и валидация*

* Валидация дает уверенность в том, что вы получите именно то что надо, или вообще ничего.

FILTER_VALIDATE_INT — проверка на целое число.
$valid_int = filter_var($int, FILTER_VALIDATE_INT);
if ($valid_int !== false)
{
  // проверка прошла успешно, $valid_int — целое число
} else {
 // проверка не прошла
}
FILTER_VALIDATE_FLOAT — проверка на число с плавающей точкой

FILTER_VALIDATE_BOOLEAN — проверка на булево число

FILTER_VALIDATE_URL — проверка на URL-адрес

FILTER_VALIDATE_EMAIL — уже знакомая нам проверка e-mail адреса

FILTER_VALIDATE_IP — проверка IP-адреса

FILTER_UNSAFE_RAW — проверка на небезопасный, "сырой" текст.

Очистка данных

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

FILTER_SANITIZE_STRING — базовая очистка строки. Удаляет символы <>?
$san_string = filter_var($string, FILTER_SANITIZE_STRING);
FILTER_SANITIZE_STRIPPED — базовая очистка строки. Удаляет символы <>?

FILTER_SANITIZE_ENCODED — кодирует символы `~!@#$%^&*()=+[{]};:'".?/| в %hex

FILTER_SANITIZE_SPECIAL_CHARS — кодирует специальные символы <>&" в &type;

FILTER_SANITIZE_EMAIL — убирает символы <>();:,\”

FILTER_SANITIZE_URL — оставляет только a-zA-Z0-9`~!@#$%^&*()-_=+[{]};:'"<,>.?/|

FILTER_SANITIZE_NUMBER_INT — оставляет только 1234567890-+

FILTER_SANITIZE_NUMBER_FLOAT — оставляет только 1234567890-+.

FILTER_SANITIZE_MAGIC_QUOTES — кодирует '”\, точно так же как и magic quotes

Флаги

Флаги — это дополнительные параметры фильтров. Большинство флагов предназначено для конкретных режимов проверки/очистки.

FILTER_FLAG_ALLOW_OCTAL (только для фильтров *_INT) — разрешает восьмеричные цифры для фильтров *_INT.
$allow_octal = filter_var($int_octal, FILTER_SANITIZE_NUMBER_INT, FILTER_FLAG_ALLOW_OCTAL);
FILTER_FLAG_ALLOW_HEX (*_INT filters only) — разрешает шестнадцатиричные цифры для фильтров *_INT.

FILTER_FLAG_STRIP_LOW — вырезает все символы, код которых меньше 32 (ASCII)

FILTER_FLAG_STRIP_HIGH — вырезает все символы с кодами больше 127 (ASCII)

FILTER_FLAG_ENCODE_LOW — кодирует все символы, код которых меньше 32 (ASCII)

FILTER_FLAG_ENCODE_HIGH — кодирует все символы с кодами больше 127 (ASCII)

FILTER_FLAG_NO_ENCODE_QUOTES — игнорирует символы ' и "

FILTER_FLAG_ALLOW_FRACTION (только для фильтров *_NUMBER_FLOAT) — разрешает только 1234567890-+.

FILTER_FLAG_ALLOW_THOUSAND (только для фильтров *_NUMBER_FLOAT) — разрешает только 1234567890-+,

FILTER_FLAG_ALLOW_SCIENTIFIC (только для фильтров *_NUMBER_FLOAT) — разрешает только eE1234567890-+

FILTER_FLAG_SCHEME_REQUIRED (только для VALIDATE_URL) — требует присутствия схемы URL (http://, ftp:// и т.д.)

FILTER_FLAG_HOST_REQUIRED (только для VALIDATE_URL) — требует присутствия URL-хоста

FILTER_FLAG_PATH_REQUIRED (только для VALIDATE_URL) — требует присутствия URL-пути

FILTER_FLAG_QUERY_REQUIRED (только для VALIDATE_URL) — требует присутствия URL строки запроса

FILTER_FLAG_IPV4 (только для VALIDATE_IP) — требует, чтобы IP-адрес был в формате IPV4

FILTER_FLAG_IPV6 (только для VALIDATE_IP) — требует, чтобы IP-адрес был в формате IPV6

FILTER_FLAG_NO_RES_RANGE (только для VALIDATE_IP) — требует, чтобы IP-адрес не был в диапазоне зарезервированных адресов

FILTER_FLAG_NO_PRIV_RANGE (только для VALIDATE_IP) — требует, чтобы IP-адрес не был в диапазоне локальных адресов

FILTER_NULL_ON_FAILURE — Возвращает null вместо пустой строки, если не проходит проверка или какой-нибудь флаг

  7 марта 2009  |    PHP  |    Spider
  php, безопасность

Комментарии (29)

Миха | 15 мая 2009, 20:09
хмммм, спасибо, я и не подозревал про существование этих функций, весьма полезные вещи, но как я погляжу появились не так давно - с версии 5.2.0 поэтому стоит обращать на это внимание
eaglenix | 9 августа 2009, 00:52
Действительно полезно и действительно пока что рано использовать, обламался на хостинге не пашет)
Mehdi | 29 августа 2009, 12:59
Огромнейшее спасибо! Я тоже не подозревал о существовании этих функций, которые так полезны :-)
Spider | 3 сентября 2009, 16:33
Mehdi, пожалуйста, я рад, что информация оказалась полезной. Действительно не очень много людей знают о функциях фильтрации переменных в PHP, в основном потому что по этой теме очень мало информации, даже официальной. А на русском языке ее вообще практически невозможно найти
Holy Diver | 3 ноября 2009, 11:20
Spider, большое спасибо за информацию на русском! Пребываю в состоянии эйфории! Теперь можно забыть о головной боли при валидации форм.
24may | 22 ноября 2009, 23:17
# $vaild_email = filter_var($email, FILTER_VALIDATE_EMAIL);  
что - то не работает
Хотя версия PHP > 5.20
Spider | 23 ноября 2009, 22:10
24may, что значит "что-то не работает"? Пишутся какие-то сообщения об ошибках, например, что функция не существует?
Смоленский | 28 декабря 2009, 22:14
24may, для работы этой функции должны быть предустановлены фильтры, иначе ничего работать не будет
ZULI | 19 апреля 2010, 02:08
В данном примере ошибочка:
 
$email = 'fgdjkdgdfghdsdfj';  
$vaild_email = filter_var($email, FILTER_VALIDATE_EMAIL);  
 
if ($valid_email !== false)  
{  
  echo "E-mail адрес корректный";  
} else {  
  echo "Некорректный E-mail адрес";  
}  
 
Буквы в слове valid перепутаны  Very we! Долго мучался пока не заметил это.
Spider | 21 апреля 2010, 15:47
ZULI, спасибо за замечание. Исправлено
АндрейКо | 17 мая 2010, 19:26
Сейчас вот попробовал проверять email адреса, но выяснилось что FILTER_VALIDATE_EMAIL пропускает в левой части( до @) кириллицу.
Например: вася@mail.ru -> выдает как вася@mail.ru
Это ошибка или так задуманно? Вроде ведь email должен состоять из латинских букв и цифр.
АндрейКо | 17 мая 2010, 19:43
Снова я. При вводе вася<script>alert("Вася")</script>@mail.ru в функцию FILTER_VALIDATE_EMAIL она выдает этот же результат. Т.е. у меня при перезагрузке выскакивает окошко с надписью Вася. Получается что эта функция ничего не защищает. Тогда зачем она нужна?
Spider | 19 мая 2010, 18:46
АндрейКо, странно. у меня скрипт
 
<?php var_dump(filter_var('Вася@mail.ru', FILTER_VALIDATE_EMAIL)); ?>
 
выдает bool(false) так же как и
 
<?php var_dump(filter_var('вася<script>alert("Вася")</script>@mail.ru', FILTER_VALIDATE_EMAIL)); ?>
Jan | 17 июня 2010, 17:05
Спасибо помоглою Также пригодиться для дальнейшего написания, а то раньше проверял какимито длиными методами.  Well
Red_Joker | 30 января 2011, 12:50
Спасибо. Очень помогло. Ну сейчас уже версия 5.3.х появилась, хоть и пока багнутая, но думаю у всех норм хостеров стоит версия выше чем 5.2.0 ))
Red_Joker | 30 января 2011, 12:58
Добавь в статью информацию о filter_input - это будет очень полезно для проверки входных данных.
Наталья | 30 января 2011, 17:24
Большое спасибо за статью! Очень и очень полезна!
Александр | 3 февраля 2011, 15:38
Спасибо, если скомбинировать несколько проверок - хорошая защита от XSS получается.
Never Lex | 2 марта 2011, 10:53
Спасибо. Единственная вменяемая статья про filter_var
Spider | 2 марта 2011, 14:36
Не за что! Я тоже заметил, что на русском языке крайне мало информации про функции фильтрации переменных в PHP, поэтому решил написать эту статью. Возможно напишу ещё что-нибудь по этой теме
Spider | 2 марта 2011, 14:39
2Red_Joker: как раз подумываю об этом. Как будет время — обязательно напишу про filter_input
Дмитрий | 17 апреля 2011, 08:32
Безумно благодарен!
Spider | 19 апреля 2011, 19:54
Дмитрий: всегда пожалуйста Well
GO | 6 декабря 2011, 13:11
Единственное что плохо, это то что фильтр FILTER_VALIDATE_EMAIL не разрешает кириллических доменов.
Например это
<?php
var_dump(filter_var("email@пример.рф", FILTER_VALIDATE_EMAIL));
?>
выведет bool(false) ..
Борис | 27 декабря 2011, 14:46
насчет FILTER_UNSAFE_RAW
что значит "сырой" текст? =)
Анон | 3 января 2012, 18:42
Шикарно, уважуха Well
Oleg | 10 января 2012, 13:02
на ввод проверки почты
$email = 'q@ga';
выдает bool(true) - E-mail адрес корректный
 
Проверочка не очень...
Spider | 17 января 2012, 02:51
GO, да, домены на национальном языке, в том числе и кириллические, не поддерживаются. Тут придётся писать свой фильтр
 
Oleg, с точки зрения стандарта это вполне корректный email. Согласен, что в реальной жизни надо более строго проверять email.
 
Вообще как мы успели убедиться, эти фильтры не очень подходят для проверки email адресов, а в остальном хорошая штука Well
Spider | 17 января 2012, 02:57
Борис, фильтр FILTER_UNSAFE_RAW используется только в комбинации с флагами (например, FILTER_FLAG_STRIP_LOW, FILTER_FLAG_STRIP_HIGH, FILTER_FLAG_ENCODE_LOW, FILTER_FLAG_ENCODE_HIGH, FILTER_FLAG_ENCODE_AMP и т.д.).
 
Сам по себе он ничего не делает, всё его поведение определяют флаги. А работают они так:
 
FILTER_FLAG_STRIP_LOW — Вырезает символы с кодом меньше 32
FILTER_FLAG_STRIP_HIGH — Вырезает символы с кодом больше 32
FILTER_FLAG_ENCODE_LOW — Кодирует символы с кодом меньше 32
FILTER_FLAG_ENCODE_HIGH — Кодирует символы с кодом больше 32
FILTER_FLAG_ENCODE_AMP — Кодирует амперсанд (&) в &amp;

Добавить комментарий

Ваше имя: *
Ваш e-mail: * (не публикуется)
Адрес сайта:
Комментарий: *
полужирный курсив курсив курсив вставить ссылку

  

Новости сайта в RSS

Категории

Статьи

Новые Популярные Комментируемые

Облако меток

Разное

Продажа авто Воронеж, покупка авто в Воронеже, авто с пробегом в Воронеже