Где я должен генерировать токены формы CSRF и CAPTCHA в приложении MVC?

Дано:

Я создал Hash а также Captcha классы. Hash создает токены формы. Captcha использует Graphics класс для создания изображения. Пользовательский класс-оболочка службы сеанса используется для обработки $_SESSION суперглобальная структура данных.

Сценарий:

Я использую контейнер для инъекций зависимости. Поэтому я хочу знать, где определить экземпляр Captcha а также Hash для общедоступных форм HTML.

Гипотеза 1: Вы должны ввести Hash а также Captcha в детстве Model потому что доступ $_SESSION требуется для хранения (по запросу HTTP) и проверки (при ответе HTTP) токенов CSRF и ответов CAPTCHA. Представление никогда не должно обращаться к структурам данных сеанса.

Гипотеза 2: Вы должны ввести Hash а также Captcha в детстве View потому что генерация токенов CSRF и CAPTCHA на самом деле является частью представления логика представления, хотя проверка их происходит в Model, Прямой или косвенный доступ к структурам данных сеанса из View разрешено

Гипотеза номер один кажется ответом, но я хочу быть уверенным.

Абстрактный пример:

$session = new Session(); // A custom wrapper class
$hash = new Hash();
$graphics = new Graphics();
$captcha = new Captcha($graphics);


$model = new ContactModel($session, $hash, $captcha);

или же

$view = new ContactView($session, $hash, $captcha);

0

Решение

Примечание № 1: Я думаю, что вы должны прочитать эта почта. Я подчеркну основную часть этого ответа: «Модель не класс или какой-либо один объект»

Заметка 2: ИМО, эта проблема присуща веб-реализациям MVC. Первая часть состоит в том, как бы я решил эту проблему; ниже описывается концептуально, почему эта проблема существует.

Мой ответ: ни.

Архитектура MVC разделена на 2 уровня: модель слой и презентация слой. Служебный объект (они находятся на уровне модели) должен создавать / сохранять соответствующие данные капчи в состояние клиента. Поскольку это, скорее всего, веб-приложение, уровень представления, в частности объект представления, должен будет запрашивать это состояние клиента у уровня модели. Происходит ли это через объект службы или объект доступа к данным для конкретной презентации, специально предназначенный для ответов состояния клиента, зависит от вашей реализации & наиболее подходящий. Именно здесь, в представлении, я бы сохранил состояние клиента в сеансе через другой объект доступа к данным или (Cookie/Session)Response абстракция *. Таким образом, представление не «обращается» к структуре данных сеанса, а использует компонент (DAO уровня представления или (Cookie/Session)Response абстракция *) для выполнения этой работы. Хотя мы не рассматриваем куки / сессии как презентацию («они не визуальные»), уровень представления отвечает за ответы, о которых файлы cookie / сессии являются не чем иным, как.

Мне трудно рассуждать, как это будет происходить в вашей среде, так как, похоже, существует смешение уровня модели. Ваш ContactModel определенно хотел бы, чтобы хэш / капча спасли состояние клиента. Вашему представлению не понадобится ни один из них, но дополнительный механизм для «ответа» состояния клиента на HTTP-запрос в форме файла cookie / сеанса.

* Symfony, как правило, полезен для этого. Я использую и DAO уровня представления и Symfony HttpFoundation объект, который может быть за бортом.

Концептуально: сессии как состояние против ответа

Фундаментальная проблема, которую вы здесь решаете, связана с реализацией веб-MVC. Уровень представления в веб-MVC обрабатывает «запрос» (делегированный контроллеру) и представляет «ответ» (определяется представлением). В HTTP файлы cookie и сеансы отправляются с запросами и изменяются в ответах. Это встроено в HTTP-запрос / ответ.

Если мы поместим сохранение сессии / куки в слой модели, мы сделаем наш уровень модели зависимым от HTTP и разрешим ему «отвечать» на запросы. Даже если мы абстрагируем суперглобальные переменные и «внедряем» абстракции (например, объекты cookie / сессии Symfony), существует внутренняя зависимость от файлов cookie / сеансов, которые являются реализациями запроса / ответа. Вы Можно делать все это на уровне модели, но я предпочитаю этого не делать. Другими словами, хотя модель является ответственный за отслеживание состояний, cookie / состояние сеанса фактически является ответом на запрос.

«Но это утечка логики, так как вы сохраняете состояние на уровне представления»

Я думаю, что вы можете посмотреть на все методы как на несколько «негерметичные», и это просто самый сплоченный способ. Конечно, мы «сохраняем» состояние на уровне представления, если вы смотрите на cookie / session как состояние. Если вы посмотрите на них как на ответ, которым они действительно являются в глазах MVC, то это вовсе не утечка. Я бы сказал, что отправка ответа (сохранение состояния сессии / файла cookie) на уровне модели хуже.

2

Другие решения

Ответ: Вы должны сгенерировать токены CSRF и значения CAPTCHA в «Модели».

причинаЦель этих значений — служить ограничением для вашей бизнес-логики, а не просто отображать значения или элементы управления в «представлении». Если бы «Просмотр» сгенерировал токены формы и значения запроса CAPTCHA, он должен был бы сообщить их обратно «Модели» (так или иначе). Это идет против течения.

В то время как гипотеза номер два осуществима, она возлагает обязанности на View, которые она не завершает полностью. В частности, View никогда не будет отвечать за проверку токенов форм или ответов CAPTCHA.

Представление может, как фиктивная мода, вставить токены формы и вызовы CAPTCHA в шаблон формы HTML (например). Это верно, однако теперь «представление» будет отвечать за сохранение ответов в какое-либо постоянное хранилище, а «модель» будет только извлекать и проверять их.

Таким образом, хранилище сессии будет действовать как задний канал между «видом» и «моделью», и, следовательно, соединяя их (даже если используется какая-то оболочка службы сеанса). Вид» не следует Передача данных делает «Модель», но это фактически то, что происходит, если «Представление» позволяет генерировать токены формы и значения ответов CAPTCHA.

Это мой ответ. Я приветствую ваши комментарии и критику.

0