Основные методы фильтрации данных в PHP

Раздел: -> Безопасность

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

Наиболее эффективное решение

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


$email = filter_var($_POST['email'], FILTER_VALIDATE_EMAIL);
if ($email === false) {
    // обработка ошибки
}
  

Access php (доступ к файлам в php)

В примере проверяется, является ли значение из $_POST['email'] корректным электронным адресом. Если нет, функция возвращает false. Для санитизации используется FILTER_SANITIZE_STRING (устарел, но в качестве примера) или FILTER_SANITIZE_SPECIAL_CHARS.

Пошаговая инструкция:

  1. Определить тип ожидаемых данных (email, URL, целое число и т.д.).
  2. Выбрать соответствующий фильтр из списка констант FILTER_VALIDATE_* или FILTER_SANITIZE_*.
  3. Передать данные и фильтр в filter_var() или filter_input().
  4. Проверить результат: если валидация не пройдена, выдать сообщение об ошибке; если санитизация - использовать очищенное значение.
  5. Никогда не доверять отфильтрованным данным как окончательно безопасным для SQL или вывода - всегда использовать подготовленные запросы и экранирование контекста.

Как фильтровать входные данные напрямую из суперглобальных массивов?

Функция filter_input() принимает тип входных данных (INPUT_GET, INPUT_POST, INPUT_COOKIE и др.), имя переменной и фильтр. Это сокращает код и гарантирует, что данные извлекаются только из указанного источника.


$user_id = filter_input(INPUT_POST, 'id', FILTER_VALIDATE_INT, array('options' => array('min_range' => 1, 'max_range' => 1000)));
if ($user_id === false || $user_id === null) {
    // неверные данные
}
  

Php filter (фильтрация данных в php)

Проблемы и ошибки:

Если переменная не существует, filter_input() возвращает null, что можно спутать с успешной валидацией. Всегда проверять на false и null отдельно.

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

Как очистить строку от нежелательных символов?

Фильтры санитизации удаляют или преобразуют опасные символы. Например, FILTER_SANITIZE_SPECIAL_CHARS экранирует HTML-сущности, а FILTER_SANITIZE_NUMBER_INT оставляет только цифры и знаки.


$clean_string = filter_var($input, FILTER_SANITIZE_SPECIAL_CHARS);
//  превратится в <script>alert('xss')</script>
  

Php пароль (работа с паролями в php)

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

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

Как проверить корректность IP-адреса или URL с дополнительными параметрами?

Фильтры FILTER_VALIDATE_IP и FILTER_VALIDATE_URL поддерживают флаги для уточнения требований. Например, только IPv4 или разрешить только URL с определёнными протоколами.


$ip = filter_var($input, FILTER_VALIDATE_IP, FILTER_FLAG_IPV4);
$url = filter_var($input, FILTER_VALIDATE_URL, FILTER_FLAG_SCHEME_REQUIRED | FILTER_FLAG_HOST_REQUIRED);
  

Tokens php (токены в php)

Проблема: фильтр FILTER_VALIDATE_URL не проверяет существование хоста, только синтаксис. Для проверки DNS необходимо использовать дополнительную функцию.

Как применить фильтр ко всем элементам массива?

Функции filter_var_array() и filter_input_array() позволяют определить фильтры для каждого ключа массива в виде ассоциативного массива или даже для всего массива целиком.


$filters = array(
    'name'    => FILTER_SANITIZE_SPECIAL_CHARS,
    'age'     => array('filter' => FILTER_VALIDATE_INT, 'options' => array('min_range' => 1)),
    'email'   => FILTER_VALIDATE_EMAIL
);
$result = filter_var_array($_POST, $filters);
  

Https load php (загрузка через https в php)

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

Как создать пользовательский фильтр?

Встроенные фильтры не покрывают всех потребностей. Можно использовать FILTER_CALLBACK с пользовательской функцией.


$validate_strength = function($value) {
    return (strlen($value) >= 8 && preg_match('/[A-Z]/', $value)) ? $value : false;
};
$password = filter_var($input, FILTER_CALLBACK, array('options' => $validate_strength));
  

Важно: callback-функция должна возвращать отфильтрованное значение или false при ошибке. Не следует выбрасывать исключения, так как filter_var() их не ловит.

Типичные ошибки при работе с фильтрацией

  • Путаница между валидацией и санитизацией: валидация проверяет формат, санитизация изменяет данные. Не следует санитизировать данные, которые потом будут проверяться на точное соответствие.
  • Игнорирование возвращаемого значения false: если фильтр возвращает false, нужно обработать ошибку, а не продолжать использовать исходные данные.
  • Использование устаревших фильтров: FILTER_SANITIZE_STRING помечен как устаревший, лучше применять htmlspecialchars() или FILTER_SANITIZE_SPECIAL_CHARS.
  • Отсутствие проверки на null при использовании filter_input().
  • Доверие к отфильтрованным данным как к полностью безопасным: фильтрация не защищает от SQL-инъекций - используйте PDO с подготовленными запросами.
- Domain block php (блокировка домена в php)
- Auth php (аутентификация в php)
- Api auth php (аутентификация api на php)

Расширенные примеры фильтрации данных

Валидация email с проверкой наличия MX-записи

Пример

function validateEmailWithMX($email) {
    if (!filter_var($email, FILTER_VALIDATE_EMAIL)) {
        return false;
    }
    $domain = substr(strrchr($email, '@'), 1);
    return checkdnsrr($domain, 'MX');
}

$test = 'user@example.com';
var_dump(validateEmailWithMX($test));
  
bool(true) // если MX-запись существует
  

Валидация URL с обязательным протоколом и проверкой доступности

Пример

$url = 'https://www.php.net';
$validated = filter_var($url, FILTER_VALIDATE_URL, FILTER_FLAG_SCHEME_REQUIRED | FILTER_FLAG_HOST_REQUIRED);
if ($validated) {
    $headers = @get_headers($url);
    $accessible = (strpos($headers[0], '200') !== false);
}
var_dump($validated, $accessible ?? false);
  
string(22) "https://www.php.net"
bool(true)
  

Фильтрация целочисленного массива с диапазонами

Пример

$input = ['5', '12', 'abc', '0', '150'];
$filters = array(
    'filter' => FILTER_VALIDATE_INT,
    'flags'  => FILTER_REQUIRE_ARRAY,
    'options' => array('min_range' => 1, 'max_range' => 100)
);
$result = filter_var_array($input, $filters);
print_r($result);
  
Array
(
    [0] => 5
    [1] => 12
    [2] => false
    [3] => false
    [4] => false
)
  

Санитизация многобайтовой строки без удаления кириллицы

Пример

$text = "Привет  мир!";
$clean = filter_var($text, FILTER_SANITIZE_FULL_SPECIAL_CHARS);
echo $clean;
  
Привет <script>alert('xss')</script> мир!
  

Пользовательский фильтр для проверки сложности пароля

Пример

$password = 'MyStr0ng!Pass';
$callback = function($value) {
    if (strlen($value) < 8) return false;
    if (!preg_match('/[A-Z]/', $value)) return false;
    if (!preg_match('/[a-z]/', $value)) return false;
    if (!preg_match('/[0-9]/', $value)) return false;
    if (!preg_match('/[!@#$%^&*(),.?":{}|<>]/', $value)) return false;
    return htmlspecialchars($value, ENT_QUOTES, 'UTF-8');
};
$filtered = filter_var($password, FILTER_CALLBACK, array('options' => $callback));
var_dump($filtered);
  
string(16) "MyStr0ng!Pass"
  

Фильтрация входных данных с filter_input_array и проверка ошибок

Пример

$definition = array(
    'username' => FILTER_SANITIZE_SPECIAL_CHARS,
    'age'      => array('filter' => FILTER_VALIDATE_INT, 'options' => array('min_range' => 0)),
    'agree'    => array('filter' => FILTER_VALIDATE_BOOLEAN, 'flags' => FILTER_NULL_ON_FAILURE)
);
$result = filter_input_array(INPUT_POST, $definition);
if ($result === null) {
    echo 'Нет данных POST';
} else {
    foreach ($result as $key => $value) {
        if ($value === false) {
            echo "Поле $key не прошло валидацию
"; } } }

Использование FILTER_SANITIZE_NUMBER_FLOAT для денежных значений

Пример

$input = '$1,234.56';
$clean = filter_var($input, FILTER_SANITIZE_NUMBER_FLOAT, FILTER_FLAG_ALLOW_FRACTION | FILTER_FLAG_ALLOW_THOUSAND);
echo $clean;
  
1234.56
  

Валидация IP-адреса с проверкой, не является ли он частным

Пример

$ip = '192.168.1.1';
$valid = filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_NO_PRIV_RANGE | FILTER_FLAG_IPV4);
var_dump($valid);
  
bool(false) // так как 192.168.0.0/16 является приватным диапазоном
  

Фильтрация данных из внешнего API с рекурсивной обработкой

Пример

function filterRecursive($data, $filter_definition) {
    if (is_array($data)) {
        return array_map(function($item) use ($filter_definition) {
            return filterRecursive($item, $filter_definition);
        }, $data);
    }
    return filter_var($data, $filter_definition);
}

$apiData = [
    'users' => [
        ['name' => 'Alice', 'email' => 'alice@test.com'],
        ['name' => '', 'email' => 'bob@test.com']
    ]
];
$cleaned = filterRecursive($apiData, FILTER_SANITIZE_SPECIAL_CHARS);
print_r($cleaned);
  
Array
(
    [users] => Array
        (
            [0] => Array
                (
                    [name] => Alice
                    [email] => alice@test.com
                )
            [1] => Array
                (
                    [name] => <Bob>
                    [email] => bob@test.com
                )
        )
)
  

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

En
Php filter (php)