Где обычно размещается логика авторизации в приложении?

Ответ

Логика авторизации (проверка прав доступа) обычно выносится в отдельный слой, часто реализуемый как Middleware (в конвейере запросов) или Сервис/Интерцептор. Это позволяет централизовать проверки и избежать дублирования кода в каждом контроллере.

Типичные места размещения:

  1. 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');
  2. Сервис авторизации (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);
  3. Аннотации/Атрибуты: В современных фреймворках проверки можно декларативно описывать прямо над методами контроллера.

    // Symfony с атрибутами
    #[IsGranted('ROLE_ADMIN')]
    #[IsGranted('POST_EDIT', subject: 'post')]
    public function edit(Post $post): Response { ... }

Ключевой принцип: Логика авторизации должна быть отделена от логики аутентификации (кто вы?) и бизнес-логики. Это повышает безопасность и упрощает тестирование.

Ответ 18+ 🔞

Да ты послушай, какая история! Вот сидишь ты, пишешь свой код, всё вроде красиво, контроллеры, модели... А потом бац — и нужно каждому челу в каждом методе впендюривать проверку: а можно ли ему сюда? А не пизданул ли он? Это ж пиздопроебина получается, одно и то же в каждом втором месте!

Так вот, чтобы не быть распиздяем, эту логику — кто что может делать — выносят в отдельный слой. Ну серьёзно, чувак, это как охрана на входе в клуб, а не тётка с вопросом в каждом углу зала.

Где эту охрану обычно ставят:

  1. 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');
  2. Сервис авторизации (Правила клуба): А это уже не просто "админ или не админ", а более хитрая жопа. Например, можешь ли ты редактировать этот конкретный пост. В 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); // Если нельзя — само всё зарубит
  3. Аннотации или Атрибуты (Табличка на двери): Современная фишка — просто повесить над методом контроллера "объявление", кто может внутрь. Красиво и наглядно.

    // Допустим, в Symfony с атрибутами
    #[IsGranted('ROLE_ADMIN')] // Во-первых, нужно быть админом
    #[IsGranted('POST_EDIT', subject: 'post')] // Во-вторых, иметь право на редактирование ЭТОГО поста
    public function edit(Post $post): Response { ... }

А главная мысль, ёпта, вот в чём: Нельзя путать вопросы "Кто ты?" (аутентификация) и "Что тебе можно?" (авторизация). Их надо держать отдельно. Так и безопаснее, и голова не болит, и тестировать эту всю хрень в изоляции — одно удовольствие. Иначе получится манда с ушами, доверия к такому коду — ноль ебать.