php проверка текста на html
Проверка (валидация) форм PHP
В этой главе будет показано, как обрабатывать формы PHP с учетом требований безопасности. Правильная валидация данных формы важна для её защиты от хакеров и спамеров!
Что такое валидация?
Валидация означает проверку данных, вводимых пользователем. В PHP доступны два типа проверки:
Валидация на стороне клиента — проверка выполняется на стороне клиента в веб-браузере.
Валидация на стороне сервера — после отправки данных на сервер их проверка осуществляется на серверной стороне.
Ниже приведена HTML-форма, которая содержит различные поля ввода: обязательные (required) и необязательные текстовые поля, переключатели (радио-кнопки) и кнопку отправки (submit). С этой формой мы будем с вами работать в этой главе. Попробуйте ввести данные:
Некоторые из правил проверки нашей формы:
Поле формы | Правила валидации |
---|---|
Имя | Обязатеьно для заполнения + Должно содержать только буквы и пробелы |
Обязатеьно для заполнения + Требуются символ собачка (@) и точка (.) | |
Веб-сайт | Необязательно для заполнения. Проверяется наличие валидного URL |
Комментарий | Необязательно для заполнения. Многострочное поле ввода (текстовое поле) |
Образование | Обязатеьно для заполнения + Должна быть выбрана хотя бы одна кнопка |
Текстовые поля
Поля для ввода имени, адреса электронной почты и веб-сайта создается с помощью элемента (от англ. input — ввод) с атрибутом type=»text», а поле для комментария применяется элемент
Радио-кнопки
В нашей форме выбор образования осуществляется с помощью элементов типа radio (переключатели), которые используют принцип логического «ИЛИ», позволяя выбрать только одно из нескольких значений: если вы выбираете одно положение, то все остальные становятся неактивными:
Элемент формы (form)
Главным для элемента является атрибут action, который указывает обработчик данных для формы. Обработчик данных — это файл, описывающий, что нужно делать с данными формы. Данные формы отправляются с помощью method = «post»:
$_SERVER [«PHP_SELF»] — это суперглобальная переменная, которая возвращает имя файла текущего выполняемого скрипта-обработчика.
Функция htmlspecialchars() преобразует данные, введенные пользователем, которые могут содержать нежелательные HTML-тэги. Производятся следующие преобразования:
‘&’ (амперсанд) преобразуется в ‘&’
‘ ‘ (знак «больше чем») преобразуется в ‘>’
Эти манипуляции предотвращает использование злоумышленниками кода путем внедрения скрипта (атаки с межсайтовым скриптингом) в формы.
Примечание о безопасности форм PHP
Если Вы используете на странице сайта PHP_SELF, то пользователь может ввести в адресной строке косую черту (/), а затем выполнить несколько команд межсайтового скриптинга (XSS).
Примечание: XSS (англ. Cross-Site Scripting — «межсайтовый скриптинг») — тип атаки на веб-системы, заключающийся во внедрении в выдаваемую веб-системой страницу вредоносного кода (который будет выполнен на компьютере пользователя при открытии им этой страницы) и взаимодействии этого кода с веб-сервером злоумышленника. XSS позволяет злоумышленникам внедрять клиентские скрипты в веб-страницы, просматриваемые другими пользователями..
Предположим, у нас есть следующая форма на странице с именем «send_form.php»:
Теперь, если пользователь вводит обычный URL-адрес в адресной строке, например «http://site_name.com/send_form.php», приведенный выше код будет преобразован в:
Теперь пользователь вводит URL-адрес в адресной строке и после косой черты несколько команд межсайтового скриптинга:
После таких манипуляция приведенный выше код будет переведен на:
Фильтрация и проверка данных PHP. Частые ошибки
Материал предназначен в основном для начинающих веб-программистов.
Введение.
Часто ко мне обращаются клиенты, у которых установлены самописные CMS или модули, написанные начинающими веб-программистами, которые не понимают, что нужно для защиты данных и зачастую копируют функции фильтрации, не задумываясь о том как они работают и что именно нужно с ними делать.
Здесь я постараюсь описать как можно подробнее частые ошибки при фильтрации данных в PHP скрипте и дать простые советы как правильно выполнить фильтрацию данных.
В сети много статей по поводу фильтрации данных, но они как правильно не полные и без подробные примеров.
Разбор полетов.
Фильтрация. Ошибка №1
Для числовых переменных используется такая проверка:
Почему она приведет к SQL инъекции? Дело в том, что пользователь может указать в переменной input_number значение:
В таком случаи проверка будет успешно пройдена, т.к. функция intval получает целочисленное значение переменной, т.е. 1, но в самой переменной $number ничего не изменилось, поэтому весь вредоносный код будет передан в SQL запрос.
Правильная фильтрация:
Конечно, условие может меняться, например если вам нужно получить только определенный диапазон:
Если вы используете чекбоксы или мультиселекты с числовыми значениями, выполните такую проверку:
array_map
Так же встречаю фильтрацию в виде:
Ничего кроме улыбки это не может вызвать 🙂
Фильтрация. Ошибка №2.
Для стринг-переменных используется такая фильтрация:
Функция addslashes экранирует спец. символы, но она не учитывает кодировку БД и возможен обход фильтрации. Не стану копировать текст автора, который описал данную уязвимость и дам просто ссылку Chris Shiflett (перевод можно поискать в рунете).
Если вы не предполагаете вхождение html тегов, то лучше всего сделать такую фильтрацию:
strip_tags — убирает html теги.
htmlspecialchars — преобразует спец. символы в html сущности.
Так вы защитите себя от XSS атаки, помимо SQL инъекции.
Если же вам нужны html теги, но только как для вывода исходного кода, то достаточно использовать:
Если вам важно, чтобы значение переменной не было пустой, то используйте функцию trim, пример:
Фильтрация. Ошибка №3.
Она касается поиска в БД.
Для поиска по числам используйте фильтрацию, описанную в первой ошибке.
Для поиска по тексту используйте фильтрацию, описанную во второй ошибке, но с оговорками.
Для того, чтобы пользователь не смог выполнить логическую ошибку, нужно удалять или экранировать спец. символы SQL.
Пример без доп. обработки строки:
На выходе у нас получится запрос вида:
Это значительно увеличит нагрузку на базу.
В своём скрипте я использую функцию, которая удаляет нежелательные мне символы из поиска:
Конечно, не все из выше перечисленных символов представляют опасность, но в моём случаи они не нужны, поэтому выполняю поиск и замену.
Пример использования фильтрации:
Также советую сделать ограничение по количеству символов в поиске, хотя бы не меньше 3-х, т.к. если у вас будет большое количество записей в базе, то поиск по 1-2 символам будет значительно увеличивать нагрузку на БД.
Фильтрация. Ошибка №4.
Не фильтруются значения в переменной $_COOKIE. Некоторые думаю, что раз эту переменную нельзя передать через форму, то это гарантия безопасности.
Данную переменную очень легко подделать любым браузером, отредактировав куки сайта.
Например, в одной известной CMS была проверка, используемого шаблона сайта:
В данном случаи можно подменить значение переменной $_COOKIE[‘skin’] и вызвать ошибку, в результате которой вы увидите абсолютный путь до папки сайта.
Если вы используете значение куков для сохранения в базу, то используйте одну из выше описанных фильтраций, тоже касается и переменной $_SERVER.
Фильтрация. Ошибка №5.
В PHP скрипте переменная $group будет равна 5, если в скрипте она не была объявлена со значением по умолчанию.
Фильтрация. Ошибка №6.
Проверка. Ошибка №1.
Сталкивался со случаями, когда для AJAX запроса (например: повышение репутации) передавалось имя пользователя или его ID (кому повышается репутация), но в самом PHP не было проверки на существование такого пользователя.
Например:
Получается мы создаем запись в базе, которая совершенно бесполезна нам.
Проверка. Ошибка №2.
При выполнении различного рода действий (добавление, редактирование, удаление) с данными не забывайте проверять права пользователя на доступ к данной функции и дополнительные возможности (использование html тегов или возможность опубликовать материал без проверки).
Давно исправлял в одном модуле форума подобную ошибку, когда любой пользователь мог отредактировать сообщение администрации.
Проверка. Ошибка №3.
При использовании нескольких php файлов сделайте простую проверку.
В файле index.php (или в любом другом главном файле) напишите такую строчку перед подключением других php файлов:
В начале других php файлов напишите:
Так вы ограничите доступ к файлам.
Проверка. Ошибка №4.
Используйте хеши для пользователей. Это поможет предотвратить вызов той или иной функции путём XSS.
Пример составления хеша для пользователей:
Далее во все важные формы подставляйте инпут со значением текущего хеша пользователя:
Во время выполнения скрипта осуществляйте проверку:
Проверка. Ошибка №5.
При выводе SQL ошибок сделайте простое ограничение к доступу информации. Например задайте пароль для GET переменной:
Это позволит скрыть от хакера информацию, которая может ему помочь во взломе сайта.
Проверка. Ошибка №5.
Старайтесь не подключать файлы, получая имена файлов извне.
Например:
В таком случаи вы предотвратите подключение файлов, которые не были вами предусмотрены.
Совет.
Для большей надежности используйте один из готовых и популярных классов для фильтрации данных, дабы самому не пропустить какие-то вредоносные символы/данные. Также в этих классах часто имеется возможность выбора фильтра данных.
UPD: Поправил пост. Перенес все советы по поводу функций и переменных, которые были в комментариях.
html_entity_decode
(PHP 4 >= 4.3.0, PHP 5, PHP 7, PHP 8)
html_entity_decode — Преобразует HTML-сущности в соответствующие им символы
Описание
Список параметров
Необязательный аргумент, определяющий кодировку, используемую при конвертации символов.
Если не указан, то значение по умолчанию для encoding зависит от конфигурационной опции default_charset.
Хотя этот аргумент является технически необязательным, настоятельно рекомендуется указать правильное значение для вашего кода, опция конфигурации default_charset может быть задана неверно для входных данных.
Поддерживаются следующие кодировки:
Кодировка | Псевдонимы | Описание |
---|---|---|
ISO-8859-1 | ISO8859-1 | Западно-европейская Latin-1. |
ISO-8859-5 | ISO8859-5 | Редко используемая кириллическая кодировка (Latin/Cyrillic). |
ISO-8859-15 | ISO8859-15 | Западно-европейская Latin-9. Добавляет знак евро, французские и финские буквы к кодировке Latin-1 (ISO-8859-1). |
UTF-8 | 8-битная Unicode, совместимая с ASCII. | |
cp866 | ibm866, 866 | Кириллическая кодировка, применяемая в DOS. |
cp1251 | Windows-1251, win-1251, 1251 | Кириллическая кодировка, применяемая в Windows. |
cp1252 | Windows-1252, 1252 | Западно-европейская кодировка, применяемая в Windows. |
KOI8-R | koi8-ru, koi8r | Русская кодировка. |
BIG5 | 950 | Традиционный китайский, применяется в основном на Тайване. |
GB2312 | 936 | Упрощённый китайский, стандартная национальная кодировка. |
BIG5-HKSCS | Расширенная Big5, применяемая в Гонконге. | |
Shift_JIS | SJIS, SJIS-win, cp932, 932 | Японская кодировка. |
EUC-JP | EUCJP, eucJP-win | Японская кодировка. |
MacRoman | Кодировка, используемая в Mac OS. | |
» | Пустая строка активирует режим определения кодировки из файла скрипта (Zend multibyte), default_charset и текущей локали (смотрите nl_langinfo() и setlocale() ) в указанном порядке. Не рекомендуется к использованию. |
Замечание: Остальные кодировки не поддерживаются, вместо них будет применена кодировка по умолчанию и сгенерировано предупреждение.
htmlentities
(PHP 4, PHP 5, PHP 7, PHP 8)
htmlentities — Преобразует все возможные символы в соответствующие HTML-сущности
Описание
Эта функция идентична htmlspecialchars() за исключением того, что htmlentities() преобразует все символы в соответствующие HTML-сущности (для тех символов, для которых HTML-сущности существуют).
Список параметров
Необязательный аргумент, определяющий кодировку, используемую при конвертации символов.
Если не указан, то значение по умолчанию для encoding зависит от конфигурационной опции default_charset.
Хотя этот аргумент является технически необязательным, настоятельно рекомендуется указать правильное значение для вашего кода, опция конфигурации default_charset может быть задана неверно для входных данных.
Поддерживаются следующие кодировки:
Кодировка | Псевдонимы | Описание |
---|---|---|
ISO-8859-1 | ISO8859-1 | Западно-европейская Latin-1. |
ISO-8859-5 | ISO8859-5 | Редко используемая кириллическая кодировка (Latin/Cyrillic). |
ISO-8859-15 | ISO8859-15 | Западно-европейская Latin-9. Добавляет знак евро, французские и финские буквы к кодировке Latin-1 (ISO-8859-1). |
UTF-8 | 8-битная Unicode, совместимая с ASCII. | |
cp866 | ibm866, 866 | Кириллическая кодировка, применяемая в DOS. |
cp1251 | Windows-1251, win-1251, 1251 | Кириллическая кодировка, применяемая в Windows. |
cp1252 | Windows-1252, 1252 | Западно-европейская кодировка, применяемая в Windows. |
KOI8-R | koi8-ru, koi8r | Русская кодировка. |
BIG5 | 950 | Традиционный китайский, применяется в основном на Тайване. |
GB2312 | 936 | Упрощённый китайский, стандартная национальная кодировка. |
BIG5-HKSCS | Расширенная Big5, применяемая в Гонконге. | |
Shift_JIS | SJIS, SJIS-win, cp932, 932 | Японская кодировка. |
EUC-JP | EUCJP, eucJP-win | Японская кодировка. |
MacRoman | Кодировка, используемая в Mac OS. | |
» | Пустая строка активирует режим определения кодировки из файла скрипта (Zend multibyte), default_charset и текущей локали (смотрите nl_langinfo() и setlocale() ) в указанном порядке. Не рекомендуется к использованию. |
Замечание: Остальные кодировки не поддерживаются, вместо них будет применена кодировка по умолчанию и сгенерировано предупреждение.
Возвращаемые значения
Возвращает преобразованную строку.
Список изменений
Примеры
Пример #1 Пример использования htmlentities()
Пример #2 Использование ENT_IGNORE
Смотрите также
User Contributed Notes 21 notes
An important note below about using this function to secure your application against Cross Site Scripting (XSS) vulnerabilities.
When printing user input in an attribute of an HTML tag, the default configuration of htmlEntities() doesn’t protect you against XSS, when using single quotes to define the border of the tag’s attribute-value. XSS is then possible by injecting a single quote:
[ ‘a’ ] = «#000′ onload=’alert(document.cookie)» ;
?>
XSS possible (insecure):
I’ve seen lots of functions to convert all the entities, but I needed to do a fulltext search in a db field that had named entities instead of numeric entities (edited by tinymce), so I searched the tinymce source and found a string with the value->entity mapping. So, i wrote the following function to encode the user’s query with named entities.
The string I used is different of the original, because i didn’t want to convert ‘ or «. The string is too long, so I had to cut it. To get the original check TinyMCE source and search for nbsp or other entity 😉
If you are building a loadvars page for Flash and have problems with special chars such as » & «, » ‘ » etc, you should escape them for flash:
Try trace(escape(«&»)); in flash’ actionscript to see the escape code for &;
The flag ENT_HTML5 also strips newline chars like \n with htmlentities while htmlspecialchars is not affected by that.
If you want to use nl2br on that string afterwards you might end up searching the problem like i did. This does not apply to other flags like e.g. ENT_XHTML which confused me.
Tested this with PHP 5.4 / 5.5 / 5.6-dev with same results, so it seems that this is an intended «feature».
For those Spanish (and not only) folks, that want their national letters back after htmlentities 🙂
The following will make a string completely safe for XML:
Как писать легко тестируемый и поддерживаемый код на PHP
Разнообразные фреймворки предоставляют инструменты для быстрой разработки приложений, но зачастую они способствуют накоплению технического долга также быстро, как позволяют создавать функциональность.
Технический долг появляется, когда сопровождение не является главной целью разработчика. Будущие изменения и отладка кода становятся затруднительными в связи с недостаточным модульным тестированием и непроработанной структурой.
В этой статье вы узнаете, как структурировать ваш код так, чтобы достичь простоты тестируемости и сопровождения – и сэкономить ваше время.
Давайте начнем с несколько выдуманного, но типичного кода. Это может быть класс в любом заданном фреймворке:
Этот код будет работать, но требует некоторых улучшений:
1. Этот код не тестируемый.
2. Данный код не такой поддерживаемый, каким бы мог быть.
Например, если мы изменим источник данных, нам нужно будет изменять код базы данных при каждом использовании App::db в нашем приложении. Кроме того непонятно, как быть в случае, когда мы хотим использовать не просто информацию о текущем пользователе?
Предпринятый модульный тест
Здесь приведена попытка создания модульного теста для функционала, описанного выше:
Для того чтобы этот модульный тест работал, нам нужно сделать следующее:
Что ж, давайте перейдем к тому, как это можно улучшить.
Придерживаемся принципа «Не повторяйся»
Этим методом мы можем пользоваться во всем нашем приложении. Мы можем передать текущего пользователя в вызове функции, вместо того, чтобы внедрять данный функционал в нашу модель. Код становится более модульным и поддерживаемым, когда перестает зависеть от других функциональных единиц (например, глобальной переменной сессии).
Однако он все еще не такой легко тестируемый и поддерживаемый, каким бы мог быть. Мы до сих пор полагаемся на соединение с базой данных.
Внедрение зависимости
Давайте поправим ситуацию путем добавления некоторых зависимостей. Здесь показано, как может выглядеть наша модель, если мы поместим соединение с базой данных в класс:
Теперь зависимости для нашей модели User обеспечены. Наш класс больше не предполагает наличие определенного подключения к базе данных, и не полагается на какие-либо глобальные объекты.
На данный момент наш класс в целом тестируемый. Мы можем передать источник данных согласно нашему выбору (по большей части) и идентификатор пользователя и протестировать результаты вызова. Также мы можем переключать соединение к нашим отдельным базам данных (предполагая, что обе базы реализуют одинаковые методы извлечения данных). Круто!
Давайте посмотрим, как выглядит модульный тест сейчас:
Я добавил кое-что новенькое в этот модульный тест: фиктивную реализацию. Фиктивная реализация позволяет нам имитировать (фальсифицировать) PHP объекты. В данном случае мы осуществляем фиктивную реализацию подключения к базе данных. С нашей « заглушкой » мы можем пропустить тестирование подключения к базе данных и просто проверить нашу модель.
Хотите узнать больше о фиктивной реализации?
Таким образом, решаются несколько проблем:
Но мы все еще можем сделать наш код гораздо лучше. С этого места начинается самое интересное.
Интерфейсы
Для дальнейшего улучшения мы можем определить и реализовать интерфейсы. Рассмотрим следующий код:
Здесь происходит несколько вещей.
Что мы имеем в результате?
А еще мы упростили наш модульный тест!
Но мы все еще можем сделать код лучше!
Контейнеры
Рассмотрим использование нашего текущего кода:
Я переместил создание модели User в одно место в конфигурации приложения. В результате:
Заключительное слово
В нашем уроке мы выполнили следующее:
Я уверен, вы заметили, что мы добавили намного больше кода для достижения простоты обслуживания и тестируемости. Сильный аргумент против такой реализации – увеличение сложности. В самом деле, для этого требуется более глубокое знание кода, как для основного разработчика, так и для остальных участников проекта.
Однако, затраты на объяснение и понимание кода с лихвой окупаются снижением технического долга.
Код стал значительно более легким в обслуживании, представилась возможность производить изменения всего в одном месте, а не в нескольких.
Возможность быстро проводить модульное тестирование снизит количество ошибок в коде со значительным отрывом – особенно в долгосрочных или разрабатываемых в сообществе (с открытым исходным кодом) проектах.
Проделывая дополнительную работу сейчас, мы сэкономим время и освободимся от головной боли в будущем.
Источники
Затем вы можете установить ваши зависимости, основанные на Composer, со следующими требованиями:
При использовании PHP фреймворка Laravel 4 применение контейнеров и других идей, описанных здесь, носит исключительно важный характер.