В каком месте MVC-концепции веб-приложения нужно фильтровать HTML-спецсимволы?

Есть веб-приложение (сайт), которое построено на идеях MVC: есть контроллер, который обрабатывает входящие запросы и возвращает ответ, представление, которое формирует HTML-код страниц и JSON-код для API, и модель, которая хранит данные и занимается так называемой бизнес-логикой.

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

Все знают, что в текстовых данных, полученных с клиента, нужно обязательно экранировать спецсимволы HTML до того, как вставлять этот текст в HTML-код страницы. Собственно вопрос: на каком этапе работы сайта нужно экранировать спецсимволы HTML:
  • в контроллере при получении данных из формы;
  • в модели перед сохранением в БД;
  • в контроллере или модели при передаче данных на представление;
  • на представлении при вставке текста в HTML;
  • или в другом месте?

Пожалуйста, аргументируйте ваш ответ.
  • Вопрос задан
  • 547 просмотров
Пригласить эксперта
Ответы на вопрос 3
xmoonlight
@xmoonlight
https://sitecoder.blogspot.com
В этом месте:
на представлении при вставке текста в HTML;

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

Если более детально: вот схема. (блоки "Подготовка выходных данных модуля" и "Подготовка выходных данных приложения")
Ответ написан
Wolfnsex
@Wolfnsex Куратор тега Веб-разработка
Если не хочешь быть первым - не вставай в очередь!
Не думаю, что у Вашего вопроса, если безусловный и едино правильный ответ. Прежде всего, всё зависит от фреймворка, которым Вы пользуетесь, соответственно, в разных фреймворках есть разные реализации таких механизмов.

Например, в Symfony2/3 есть такая штука как "DataTransformers", которая преобразует данные при сохранении/извлечении по заданной формуле. В Laravel 5.x - есть "Мутаторы", которые произволят аналогичные манипуляции с полями модели. Так же в зависимости от фреймворка, могут быть разнообразные фильтры, преобразователи и так далее.

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

Но, давайте рассуждать логически. Вам когда-нибудь будет нужен текст 100% оригинал? То есть, такой текст, который бы сохранил все теги, которые ввёл пользователь, все пробелы (в том числе и лишние), регистр этих тегов и пр. подробности/особенности того, что пользователь ввёл?

Если да, но эти данные Вам будут нужны редко, для какой-то статистики например - то сохраняйте их в каком-то отдельном поле в БД, типа "user_text_original".

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

И, самый вероятный вариант:
Если же, данные в их оригинальном виде Вам не нужны в 99% случаев, а нужны Вам уже отфильтрованные данные, с которых вычищены все лишние HTML-теги например, то возникает резонный вопрос: зачем постоянно гонять фильтры туда-суда, сохраняйте сразу отфильтрованные данные в БД, в соответствии с возможностями и механизмами Вашего фреймворка (как я уже писал выше, это могут быть DataTransformer'ы, Мутаторы и т.д.). Так как Вы удаляете из данных теги - их объём сокращается (это плюс), и так как Вы дёргаете фильтр всего 1 раз, сокращается нагрузка на систему (это так же плюс). Но такой расклад будет работать только в том случае, если сохраненные данные будут получаться чаще, чем сохраняться. То, например, если Вы выводите на страницу комментарии, то каждая независимая единица комментария, должна быть показана хотя бы 2 раза. То есть, если у Вас есть 1000 комментариев всего, то обработаться/отобразиться за всё время жизнедеятельности сайта, должно не менее 1000 комментариев, иначе фильтр будет убыточен с точки зрения производительности (такой вариант мало вероятен, но гипотетически возможен, что у Вас данные добавляются чаще, чем отображаются/обрабатываются хотя бы раз).

Я надеюсь, Вы поняли мысль, которую я хотел донести. MVC - это модель архитектуры приложения, довольно общая. В ней нет строгого деления или описания каких-то отдельных менанизмов, вроде обработки запросов или фильтрации данных. К тому же, MVC как архитектура/концепция была описана в 1979 году, несколько раньше чем появилось понятие "веб" или уже тем более "современный веб".

P.S. Я бы конечно мог расписать всё ещё более подробно, но и так много получилось...
Ответ написан
miraage
@miraage
Старый прогер
Защита простая (всякие csrf итд не упоминаю)

1) перед ставкой в базу экранировать данные от SQL инъекций
2) перед выводом в браузер экранировать данные от XSS атак
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы