Статьи

Проверка входных данных с использованием функций фильтра

Я хотел бы начать с этой статьи, поблагодарив вас за то, что сделали это даже так далеко. Я полностью осознаю, что «Проверка входных данных с использованием функций фильтра» — это не самый сексуальный заголовок статьи в мире!

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

В этой статье я объясню, почему проверка ввода важна, почему важно использовать встроенные функции PHP для выполнения проверки ввода, а затем filter_input() несколько примеров (а именно использование filter_input() и filter_var() ), обсудим некоторые потенциальные ловушки, и закончите с красивым, сочным призывом к действию. Звучит неплохо? Пошли!

Почему проверка входных данных важна

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

К сожалению, как программисты мы часто пишем вещи, думая только о том, как мы хотим, чтобы они работали. Мы не учитываем, как кто-то другой может заставить их работать — из любопытства, невежества или злобы.

Я не буду вдаваться в подробности о проблеме, с которой вы можете столкнуться, если вы не подтвердите ввод данных пользователем; На этом самом сайте есть действительно хорошая статья под названием PHP Security: Атаки с использованием межсайтовых сценариев, если вы хотите прочитать об этом. Но я скажу, что проверка вашего ввода — это первый шаг к тому, чтобы гарантировать, что написанный вами код будет выполнен так, как задумано.

Может быть, вы переходите на PHP с другого языка, и вы можете подумать: «Это никогда не было проблемой раньше, так почему меня это должно волновать?». Причина в том, что проверка правильности заключается в том, что PHP имеет свободную типизацию. Это делает PHP отличным для некоторых вещей, но это может сделать такие вещи, как проверка данных, немного сложнее, потому что вы можете в значительной степени передать что угодно чему угодно.

Почему важно использовать встроенные методы

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

Когда вы применяете свои собственные методы проверки, вы обычно попадаете в ту же ловушку, в которую можете попасть при разработке других функций: вы думаете о крайних случаях, о которых вы хотите подумать, а не обязательно о всех различных векторах, которые можно использовать для маскировки. определенный вклад. Другая проблема заключается в том, что если вы чем-то похожи на меня, первые 10 минут любого обзора кода, касающегося свернутого вручную кода проверки, тратятся на то, чтобы сделать это, потому что программист сделал не совсем то, что сделал бы вы. Это может привести к тому, что программисты будут тратить больше времени на изучение кодовой базы и чтение внутренней документации, которую вместо этого можно было бы потратить на кодирование.

Некоторые люди не катят свои собственные, а вместо этого выбирают стороннее решение. Есть несколько хороших, и в прошлом я использовал OWASP ESAPI для дополнительной проверки. Это лучше, чем, возможно, ручные решения, потому что на них смотрят больше глаз, но тогда у вас есть проблема с введением стороннего кода в ваш проект. Опять же, это увеличивает время, затрачиваемое на изучение кодовой базы и чтение дополнительной документации вместо кодирования.

По этим причинам лучше использовать нативные функции; Более того, поскольку такие функции встроены в язык, это означает, что у нас есть одно место для всей документации PHP. У новых разработчиков будет больше шансов узнать, что такое код и как его лучше всего использовать. Это будет легче поддерживать в результате этого.

Надеюсь, к настоящему моменту я убедил вас, что валидация важна и что было бы неплохо использовать функции PHP, чтобы помочь вам достичь ваших потребностей в валидации. Если вы не уверены, оставьте комментарий и давайте обсудим его.

Несколько примеров

Функция filter_input () была введена в PHP 5.2.0 и позволяет вам получать внешнюю переменную по имени и фильтровать ее. Это невероятно полезно при работе с данными $_GET и $_POST .

Давайте возьмем в качестве примера простую страницу, которая считывает значение, переданное из URL, и обрабатывает его. Мы знаем, что это значение должно быть целым числом от 15 до 20.
Один из способов сделать что-то вроде:

 <?php if (isset($_GET["value"])) { $value = $_GET["value"]; } else { $value = false; } if (is_numeric($value) && ($value >= 15 && $value <= 20)) { // run my code } else { // handle the issue } 

Это действительно простой пример, и мы уже пишем больше строк, которые я хотел бы видеть.

Во-первых, поскольку мы не можем быть уверены, что $_GET установлен, код выполняет соответствующую проверку, чтобы сценарий не выпал.

Следующим является тот факт, что $value теперь является «грязной» переменной, поскольку она была напрямую назначена из значения $_GET . Нам нужно позаботиться о том, чтобы не использовать $value где-либо еще в коде на случай, если мы что-нибудь сломаем.

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

И, наконец, у нас есть проблема с тем фактом, что оператор if немного утомителен для восприятия и является дополнительной логикой для проработки, когда вы просматриваете код.

Сравните приведенный выше пример с этим:

 <?php $value = filter_input(INPUT_GET, "value", FILTER_VALIDATE_INT, array("options" => array("min_range" => 15, "max_range" => 20))); if ($value) { // run my code } else { // handle the issue } 

Разве это не заставляет вас чувствовать себя тепло и нечетко?

filter_input() обрабатывает не установленное значение $_GET , поэтому вам не нужно беспокоиться о том, получает ли скрипт правильную информацию или нет.

Вам также не нужно беспокоиться о том, что $value быть грязным, потому что он был проверен до того, как был назначен.

Обратите внимание, что 16.0 больше не действует.

И, наконец, наша логика больше не сложна. Это просто быстрая проверка истинного значения ( filter_input() вернет false, если проверка не filter_input() и null, если $_GET["value"] не было установлено).

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

Теперь вы можете подумать, что это может быть полезно для простых скриптов, которые захватывают пару переменных $_GET или $_POST , но как насчет использования внутри функций или классов? К счастью, у нас есть filter_var () для этого.

Функция filter_var() была введена одновременно с filter_input() и делает то же самое.

 <?php // This is a sample function, do not use this to actually email, // that would be silly. function emailUser($email) { mail($email, "Here is my email", "Some Content"); } 

Опасность здесь в том, что ничто не мешает функции mail() пытаться отправить электронное письмо буквально на любое значение, которое может быть сохранено в $email . Это может привести к тому, что электронные письма не будут отправлены, или что-то получит, что потенциально может использовать функцию для злонамеренных действий в худшем случае.

Я видел, как люди проверяли результат работы mail() , и было бы хорошо видеть, успешно ли завершена функция, но к тому времени, когда возвращается значение, ущерб уже нанесен.

Нечто подобное гораздо более вменяемое

 <?php // This is a sample function, do not use this to actually email, // that would be silly. function emailUser($email) { $email = filter_var($email, FILTER_VALIDATE_EMAIL); if ($email !== false) { mail($email, "Here is my email", "Some Content"); } else { // handle the issue invalid email address } } 

Проблема с множеством примеров, включая приведенные выше, заключается в том, что они являются базовыми. Вы можете подумать, что filter_var() или filter_input() нельзя использовать ни для чего, кроме базовой проверки. Прекрасные ребята, которые представили эти функции, рассмотрели это и позволили вам передать фильтр этим функциям с именем FILTER_CALLBACK .

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

Некоторые потенциальные ловушки

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

Основной недостаток заключается в том, что функции работают так же хорошо, как фильтр, который вы применяете к нему. Возьмем последний пример с использованием проверки электронной почты — FILTER_VALIDATE_EMAIL обрабатывает адреса электронной почты изменился с 5.2.14 до 5.3.3, и даже если предположить, что все ваши приложения работают на одной и той же версии PHP, существуют адреса электронной почты, которые технически действительны, чего вы не ожидаете , Убедитесь, что вы знаете о фильтрах, которые вы используете.

Вторая проблема заключается в том, что люди думают, что если они вставят несколько фильтров, то их код будет безопасным. Фильтрация ваших переменных помогает вам, но не делает ваш код на 100% безопасным от злоупотреблений. Я хотел бы поговорить об этом подробнее, но это выходит за рамки этой статьи, и мое количество слов уже довольно высоко!

Вывод

Надеюсь, вы нашли это введение в проверку ввода в PHP полезным. А теперь время призывать к действию!

Я хочу, чтобы вы взяли одну функцию в своем коде, только одну, и посмотрите, что происходит с ней, когда вы передаете разные типы данных и разные значения. Затем я хочу, чтобы вы применили некоторые из методов фильтрации, обсуждаемых здесь, и посмотрите, есть ли разница в том, как работает ваш код. Я хотел бы знать, как вы поживали в комментариях.

Изображение с помощью Chance Agrella / Freerangestock.com