Можно ли проверить, защищен ли URL / маршрут за брандмауэром программно? - PullRequest
6 голосов
/ 13 октября 2011

У меня есть ситуация, когда мне нужно запустить какой-то код, если пользователь пытается получить доступ к защищенному URL-адресу и не аутентифицирован / авторизован.

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

Лучший способ справиться с этим - создать пользовательский прослушиватель, который прослушивает событие kernel.request и проверяет две вещи:

  • проверяет, является ли метод запроса POST
  • проверяет, является ли пользователь полностью проверка подлинности

Если это запрос POST и пользователь не полностью аутентифицирован, я бы повторил объект JSON.

Но мой слушатель (как ожидается) запускает все запросы - я бы хотел ограничить его только проверкой, относится ли запрос к URL-адресу, защищенному брандмауэром. Можно ли проверить это программно?

У меня также есть ноющее подозрение, что есть более простой способ сделать это, но я не могу понять это, поэтому, если у кого-то есть какие-либо советы, я бы хотел их услышать:)

Редактировать
@Problematic - причина проверки только запросов с брандмауэром заключается в том, что у меня есть некоторые запросы, которые не берутся за брандмауэр, и если мой код будет запущен, я получу вышеупомянутый объект JSON вместо реального ответа на запрос.

Прямо сейчас, если я не вошел в систему и не сделал POST-запрос к api/get/something (который находится за брандмауэром), Symfony возвращает HTML-код, описывающий страницу входа. Вместо этого я хочу просто повторить что-то вроде {error: 'User is not authorized'}. Но я хочу, чтобы это происходило только для POST-запросов.

1 Ответ

3 голосов
/ 14 октября 2011

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

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

  • Symfony\Component\Security\Http\Firewall слушает kernel.request событие
  • Брандмауэр затем вызывает несколько прослушивателей событий, зарегистрированных в security.yml
  • Если обнаружено какое-либо нарушение безопасности (т. Е. Пользователь пытается получить доступ к чему-либо без входа в систему), выдается AccessDeniedException и отправляется событие kernel.exception.
  • Symfony/Component/Security/Http/Firewall/ExceptionListener прослушивает событие и запускает его метод onKernelException, который решает, каким будет следующий шаг. В моем случае это запустит процесс аутентификации

Поскольку запуск процесса аутентификации - это то, чего я хотел избежать, я написал свой собственный прослушиватель событий, который перехватывает kernel.exception до того, как ExceptionListener Symfony делает. Я назначил слушателю события приоритет 1.

Это метод, который я написал:

public function handleException(GetResponseForExceptionEvent $event) {
        $exception = $event->getException();
        $request = $event->getRequest();
        if ($request->getMethod() == 'POST') {
            if ($exception instanceof AccessDeniedException) {
                $response = new Response({err: 'not logged in'});
                $event->setResponse($response);
            }
        }
    }

Пока пользователь не авторизован и метод запроса POST, возвращается объект JSON (который также останавливает распространение события) вместо HTML для страницы входа. В противном случае, другие слушатели kernel.exception отреагируют, и Symfony сможет заняться своими делами.

Итак, оригинальный вопрос остается без ответа, но я думаю, что это можно сделать, проверив, есть ли у пользователя доступ к действию. Symfony\Component\Security\Core\Authorization\AccessDecisionManager похоже, это было бы полезно для этого.

Редактировать
Я не знаю, если этот метод только обрабатывает пользователей, которые не вошли в систему. Я еще не проверял его, но я думаю, что он также будет срабатывать, если (вошедший в систему) пользователь попытается получить доступ к действию это требует роли, которую они не получили. Если это вызывает проблемы, я бы попытался изменить его для использования метода Symfony\Component\Security\Core\Authentication\AuthenticationTrustResolver isFullFledged($token), чтобы заботиться только о пользователях, которые не вошли в систему.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...