Как правильно оформить кастомную аутентификацию в Symfony2? Сразу оговорюсь, что официальная документация с примером WSSE-аутентификации не очень прояснила мне суть вопроса.
Необходимо сделать аутентификацию через метод API сервиса, который внешне похож на OpenID, но им не является. Механика работы аутентификации:
1. Проверка аутентификации пользователя и, если он не аутентифицирован то выдать ему сообщение с предложением пройти на страницу аутентификации. Тут срабатывает мой контроллер, отображающий выбор региона, а потом переадресовывающий пользователя на нужный метод API.
2. На странице он должен будет выбрать один параметр: регион. При клике на кнопку нужного ему региона пользователь попадает вызывает определённый Action контроллера (либо же это правильнее сделать внутри механизма аутентификации, но тогда как и куда редиректить пользователя?), где происходит запрос к API внешнего сервиса нужного региона (регион запоминается) для получения уникальной ссылки аутентификации, после чего пользователь редиректится по этой ссылке, где он должен будет подтвердить передачу сайту данных: токена доступа к API этого самого внешнего сервиса, юзернейма во внешнем сервисе и айдишника там же. Тут непонятно, правильно ли будет делать это в контроллере, или надо переложить это тоже на кастомную аутентификацию? Если надо переложить, то как? После клика по кнопке региона от пользователя до возврата с данными на сайт больше ничего не потребуется.
3. После подтверждения пользователь редиректится обратно на сайт (в первом запросе внешнему API передаётся путь, куда редиректить пользователя), на страницу, которая принимает данные - токен, юзернейм, айдишник.
4. Система аутентификации в Listener'е создаёт токен, записывает в него пришедшие данные и отправляет токен на проверку:protected function attemptAuthentication(Request $request)
{
if ($request->get($this->options['status_parameter'], null, true) == 'ok') {
// Наполнение токена данными
return $this->authenticationManager->authenticate($token);
}
}
Тут, к счастью, всё понятно. Разве что, хотелось бы уточнить, когда вызывается метод attemptAtuthentication() у Listener'а. Если только при переходе на адрес, который указан в файрволе как адрес проверки данный - значит я всё правильно понял.
5. В дело вступает кастомный провайдер аутентификации. В методе authenticate() происходит вызов другого метода, который делает запрос ко внешнему сервису для проверки валидности токена (ведь с редиректом можно вернуть фальшивый юзернейм) и, если токен валидный - происходит поиск пользователя с таким юзернеймом, который указан в токене через userProvider:$user = $this->userProvider->loadUserByUsername($token->getUsername());
Если пользователь не существует - его нужно создать и задать ему юзернейм, и параметр айди на внешнем сервисе (не внутренний id, который primary key, а дополнительное поле, которое хранит внешний id).if (!$user) {
$user = new User();
$user->setUsername($token->getUser());
//...
// Setting role
//...
}
В итоге у нас получается либо новый пользователь, либо найденный в базе. Новому токену задаётся юзер и статус аутентификации:public function authenticate(TokenInterface $token)
{
// Тут вышеописанная рутина
$authenticatedToken->setUser($user);
$authenticatedToken->setAuthenticated(true);
return $authenticatedToken;
}Здесь непонятно то, как можно в методе authenticate() провайдера аутентификации инициировать создание пользователя, ведь это не контроллер и тут просто так не получить менеджер сущностей и отправив нового пользователя на сохранение$em = $this->getDoctrine()->getManager();
$em->persist($user);
$em->flush();Наверное, мне нужно каким-то образом передать в конструктор провайдера сервис Doctrine?
6. После этого, по идее, где-то нужно положить текущий токен в контекст безопасности, да и пользователя где-то нужно положить так, чтобы в дальнейшем он был прозрачно доступен по $this->getUser() в контроллерах. Тут непонятно, где конкретно это сделать будет правильно. Или система аутентификации позаботится об этом сама?
7. Ну и как-то после этого процесса нужно опять же выдать свой кастомный ответ в JSON о том, что аутентификация пройдена.
P.S. Сейчас имеется токен, который, кажется, реализован правильно. По крайней мере, с ним всё просто и понятно. Ещё имеется Listener унаследованный от AbstractAuthenticationListener. У абстрактного класса в параметрах есть 'login_path'. Я так понимаю, где-то там мне и нужно отображать выбор региона для пользователя, но так как это обрабатывает бандл Security, а не мои контроллеры - я пока не понимаю, как это реализовать. 'check_path' - это, как я понимаю, страница, куда пользователь должен приземлиться после редиректа со стороннего сервиса (в случае с обычной формой логина сюда должны прилетать данные формы, так?).
P.P.S. Официальную документацию читал. Там речь о WSSE, у которого другой принцип работы. И эту статью - тоже. Благодаря ним частично разобрался, но всё вышеописанное - пробелы после чтения.
Прошу прощения за такой объёмный "вопрос". Подозреваю, что может вскрыться что-то ещё, что я не понял, но если разберусь с вышеописанным механизмом - будет значительно проще разбираться дальше.

21 Авг 2019 в 07:09
178 +1
0
Ответы
1

Для реализации кастомной аутентификации в Symfony2, в вашем случае, можно применить следующий подход:

Создайте свой собственный провайдер аутентификации, который будет отвечать за проверку валидности токена и создание пользователя (при необходимости). Вы можете передать сервис doctrine в конструктор провайдера для работы с базой данных.

В методе authenticate() вашего провайдера вы можете использовать doctrine для создания нового пользователя и сохранения его в базе данных.

После успешной аутентификации и создания пользователя, вы можете установить текущий токен в контекст безопасности и связать его с пользователем.

Для возврата кастомного ответа в JSON о успешной аутентификации, вы можете создать свой Event Listener, который будет отлавливать событие успешной аутентификации и формировать нужный вам ответ.

Для отображения страницы выбора региона, вы можете использовать событие InteractiveLoginEvent, которое возникает после успешного входа пользователя. В обработчике этого события вы можете сделать редирект на страницу выбора региона.

Необходимо также настроить ваш файл security.yml, указав пути для проверки процесса аутентификации и входа пользователя (логин и проверка аутентификации). Также укажите свой кастомный провайдер аутентификации и Event Listener для обработки событий.

Надеюсь, что эти указания помогут вам с реализацией кастомной аутентификации в Symfony2. Если у вас возникнут дополнительные вопросы, не стесняйтесь задавать их.

20 Апр в 13:06
Не можешь разобраться в этой теме?
Обратись за помощью к экспертам
Название заказа не должно быть пустым
Введите email
Бесплатные доработки
Гарантированные бесплатные доработки
Быстрое выполнение
Быстрое выполнение от 2 часов
Проверка работы
Проверка работы на плагиат
Интересные статьи из справочника
Поможем написать учебную работу
Название заказа не должно быть пустым
Введите email
Доверьте свою работу экспертам
Разместите заказ
Наша система отправит ваш заказ на оценку 92 588 авторам
Первые отклики появятся уже в течение 10 минут
Прямой эфир