Ответ
Логика авторизации (проверка прав доступа) обычно выносится в отдельный слой, часто реализуемый как Middleware (в конвейере запросов) или Сервис/Интерцептор. Это позволяет централизовать проверки и избежать дублирования кода в каждом контроллере.
Типичные места размещения:
-
Middleware/Фильтр: Проверяет каждый входящий запрос перед передачей в контроллер. Это идеальное место для проверки JWT-токенов, ролей пользователя.
// Laravel-style Middleware class CheckAdminRole { public function handle($request, Closure $next) { $user = Auth::user(); if (!$user || !$user->hasRole('admin')) { abort(403, 'Forbidden'); } return $next($request); } } // Маршрут с применением middleware Route::get('/admin/dashboard', [AdminController::class, 'index'])->middleware('auth', 'role:admin'); -
Сервис авторизации (Policy/Guard): Содержит бизнес-логику проверок. В Laravel это Policies, в Symfony — Voters.
// Policy в Laravel class PostPolicy { public function update(User $user, Post $post): bool { // Пользователь может редактировать только свои посты return $user->id === $post->user_id; } } // Использование в контроллере $this->authorize('update', $post); -
Аннотации/Атрибуты: В современных фреймворках проверки можно декларативно описывать прямо над методами контроллера.
// Symfony с атрибутами #[IsGranted('ROLE_ADMIN')] #[IsGranted('POST_EDIT', subject: 'post')] public function edit(Post $post): Response { ... }
Ключевой принцип: Логика авторизации должна быть отделена от логики аутентификации (кто вы?) и бизнес-логики. Это повышает безопасность и упрощает тестирование.
Ответ 18+ 🔞
Да ты послушай, какая история! Вот сидишь ты, пишешь свой код, всё вроде красиво, контроллеры, модели... А потом бац — и нужно каждому челу в каждом методе впендюривать проверку: а можно ли ему сюда? А не пизданул ли он? Это ж пиздопроебина получается, одно и то же в каждом втором месте!
Так вот, чтобы не быть распиздяем, эту логику — кто что может делать — выносят в отдельный слой. Ну серьёзно, чувак, это как охрана на входе в клуб, а не тётка с вопросом в каждом углу зала.
Где эту охрану обычно ставят:
-
Middleware или Фильтр (Охранник на входе): Этот типчик ловит каждый запрос ещё до того, как тот доберётся до контроллера. Идеально, чтобы проверить токен или, например, гонять всех, у кого нет корочки "Админ".
// Примерно так это в Laravel выглядит class CheckAdminRole { public function handle($request, Closure $next) { $user = Auth::user(); // Если юзера нет или он не админ — в пизду, 403 ошибка if (!$user || !$user->hasRole('admin')) { abort(403, 'Forbidden'); } // Всё чисто, проходи, браток return $next($request); } } // И на маршруте вешаем этого охранника Route::get('/admin/dashboard', [AdminController::class, 'index'])->middleware('auth', 'role:admin'); -
Сервис авторизации (Правила клуба): А это уже не просто "админ или не админ", а более хитрая жопа. Например, можешь ли ты редактировать этот конкретный пост. В Laravel это Policies, в Symfony — Voters.
// Допустим, Policy в Laravel class PostPolicy { public function update(User $user, Post $post): bool { // Правило простое: редактировать пост может только его автор return $user->id === $post->user_id; } } // А в контроллере просто спрашиваем: "А можно?" $this->authorize('update', $post); // Если нельзя — само всё зарубит -
Аннотации или Атрибуты (Табличка на двери): Современная фишка — просто повесить над методом контроллера "объявление", кто может внутрь. Красиво и наглядно.
// Допустим, в Symfony с атрибутами #[IsGranted('ROLE_ADMIN')] // Во-первых, нужно быть админом #[IsGranted('POST_EDIT', subject: 'post')] // Во-вторых, иметь право на редактирование ЭТОГО поста public function edit(Post $post): Response { ... }
А главная мысль, ёпта, вот в чём: Нельзя путать вопросы "Кто ты?" (аутентификация) и "Что тебе можно?" (авторизация). Их надо держать отдельно. Так и безопаснее, и голова не болит, и тестировать эту всю хрень в изоляции — одно удовольствие. Иначе получится манда с ушами, доверия к такому коду — ноль ебать.