Найденная модель ещё не означает разрешённый просмотр
Laravel умеет автоматически получать модель для параметра маршрута. Этот механизм связывания удобен: контроллер получает найденную запись вместо ручного поиска по идентификатору. Однако само обнаружение модели не определяет право посетителя видеть её содержимое. Представим две вымышленные записи блога о комнатных растениях. Первая опубликована, вторая пока является черновиком автора. Главная страница выбирает только опубликованные записи. Если отдельная страница получает любую существующую запись без проверки видимости, второе правило отличается от первого. Отсутствие ссылки в интерфейсе не устраняет возможность обратиться к маршруту напрямую. Поэтому проверять нужно и список, и отдельную страницу.
Правило видимости должно быть названо явно
Для нашего примера договоримся: гость читает только опубликованное, автор видит собственный черновик в личной части, другой автор его не видит. Это выбранные требования приложения, а не универсальные правила любого блога. Сначала запишите их словами, затем распределите проверки по маршрутам. В Eloquent повторяющиеся условия выборки можно оформить как область запроса. Например, условие опубликованности используют при получении публичного списка и при поиске публичной записи. Но наличие такой области само по себе ничего не меняет: соответствующий запрос должен её применять. Аналогично политика доступа организует разрешения на действия с моделью, однако разработчику нужно вызвать проверку в нужном месте. Объявленное правило и фактически выполненная проверка являются разными вещами.
Чтение и изменение требуют разных решений
Авторизация отвечает на вопрос о разрешённом действии, а вход в аккаунт только устанавливает пользователя. Из того, что посетитель вошёл, не следует право менять чужие записи. В нашем блоге автор может редактировать собственный черновик, но обычный читатель опубликованной статьи не получает права её исправлять. Политика модели позволяет отдельно описать просмотр и изменение. При этом разрешение открыть раздел со списком не фильтрует автоматически каждую строку выборки по индивидуальным правам. Для списков всё равно требуется подходящий запрос. Это особенно заметно, когда блог растёт: появляются поиск, подборка похожих материалов или предварительный просмотр. Новая точка выдачи данных должна соблюдать то же правило видимости. Проверка ответа тоже должна быть содержательной. Недостаточно увидеть отсутствие кнопки редактирования: важно, чтобы запрещённый запрос не возвращал текст черновика и не менял данные.
Попробуйте на практике
На бумаге составьте проверку доступа для собственного учебного приложения или вымышленного блога. Используйте только специально созданные тестовые записи и аккаунты, без чужих данных.
- Создайте описание двух записей: опубликованной и черновика автора А. Обозначьте три роли: гость, автор А и другой автор Б.
- Запишите ожидаемые результаты для гостевого списка и прямого просмотра обеих записей. В нашем варианте гость получает опубликованную, а содержимое черновика ему недоступно.
- Добавьте проверку личного просмотра: автор А видит свой черновик, автор Б не видит чужой. Отдельно запишите, кто может изменить запись.
- Для каждой проверки назовите механизм: условие выборки, проверка политики или сочетание обоих. Если приложение существует, проверяйте эти случаи в его тестовой среде.
Как проверить результат. Список и отдельная страница согласованы. Гость не получает черновик, автор А видит свой материал, автор Б не получает чужой, а разрешение на чтение не превращается в разрешение на изменение.
Частые вопросы
Достаточно ли сделать адрес черновика трудным для угадывания?
Нет. Адрес не заменяет проверку доступа. Правило должно действовать и тогда, когда посетителю уже известен идентификатор записи.
Нужно ли обязательно скрывать запрет именно ответом 404?
Это зависит от принятой в приложении политики. Существенно, чтобы запрещённый запрос не раскрывал содержимое и обрабатывался согласованно. Выбранное поведение стоит зафиксировать в тестах вместе с правилами доступа.
Самостоятельный разбор темы. Содержание конкретной обучающей программы здесь не представлено.