воскресенье, 8 июля 2012 г.

Фильтрация переменных с числами

Часто встречаю вопросы о том, что же делать, как залатать дыры в коде?
Первая часть из цикла.

"Дыра в коде" - в первую очередь необдуманность кода, недостаточная внимательность программиста, что позволяет срабатывать скрипт не так, как было запланировано изначально.
Самой важной фразой, которую вы должны раз и навсегда запомнить, это:
Любой пользователь - это потенциальный хакер.
Частая ошибка, которую допускают начинающие - это недостаточная проверка наличия цифр в переменных, полученных от пользователя. В переменных, где должны быть числа, должны быть только числа, и не более того (к примеру, в номере странице, id записи, id пользователя и прочее).
У нас есть два способа защитить скрипт от некорректных данных пользователя - валидация (то есть, проверка значения) и фильтрация (очистка переменной от некорректного значения).

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


Первое, что приходит на ум для валидации переменной на наличие числа - функция is_numeric.
С её помощью можно всегда проверить, находится в переменной только число, или есть в наличии и другие символы. Если там находятся не только численные данные - функция возвратит false. Данная функция не лишена некоторых "неочевидностей" - она также считает нормальным числом -1, -100e50, 2.3 и прочие, и это обязательно иметь в виду.


Но более простым способом защиты скрипта для новичков будет именно фильтрация, которой занимаются две функции — abs и intval.
Abs возвращает модуль числа (для тех, кто прогулял 5-6 класс по математике - фактически удаляет отрицательные числа), но при этом оставляет дробные числа, intval - отбрасывает дробную часть, но при этом может оставить отрицательное значение. Так как отрицательное значение, как и дробное, в скриптах необходимо крайне редко, намного проще использовать эти функции вместе.
Пример использования вместе и возвращаемые результаты мы видим ниже:
<?php
echo abs(intval(1)); //1
echo abs(intval(-1)); //1
echo abs(intval(0)); //0
echo abs(intval(1.2)); //1
echo abs(intval('1 hacker')); //1
echo abs(intval('I am hacker')); //0
echo abs(intval(1000)); //1000
?>
В итоге, данный "фильтр" отбрасывает дробную часть, знак "минус" и любые буквы, которые идут после чисел.
Использование кода $id=abs(intval($_GET['id'])); защищает скрипт от самых разных неожиданностей в плане корректности численных переменных и не даст использовать хакеру подвид sql-инъекций, которые используют недостаточную фильтрацию чисел.
Важно заметить, что использование кода выше будет создавать ошибку "Notice", если не ввести переменную id, поэтому неплохо будет проверить существование переменной, и если её нет - дать значение ноль.
Как вы читали ниже, для этого есть функция isset, в итоге, 100% безошибочная фильтрация переменной, которая возвратит только положительные целые числа либо ноль, выглядит так:
<?php
if(isset($_GET['id']))
        $id=abs(intval($_GET['id']);
else    $id=0;
?>
или же этот же код, но в одну строчку для краткости с помощью тернарного оператора:
<?php
$id=isset($_GET['id']) ? abs(intval($_GET['id'])) : 0;
?>
(О синтаксисе тернарного оператора посмотреть можно здесь: http://php.net/manual/ru/language.operators.comparison.php).

Спасибо за внимание!

Комментариев нет:

Отправить комментарий