@fattan
программист

Как грамотно организовать в Symfony3 подгрузку ролей из БД?

Я почти у цели.
Есть таблица User, таблица Role, таблица user_role для связи many-to-many юзеров и ролей.
Модель юзеров предоставляет метод getRoles() и
реализует UserInterface


namespace AppBundle\Entity;

use Symfony\Component\Security\Core\User\UserInterface;
use Doctrine\Common\Collections\ArrayCollection;

class User implements UserInterface
{

	// ...

    /**
     * @var \Doctrine\Common\Collections\Collection
     */
    private $userRoles;

    /**
     * Constructor
     */
    public function __construct()
    {
        $this->userRoles = new \Doctrine\Common\Collections\ArrayCollection();
    }

    /**
     * Get userRoles
     *
     * @return \Doctrine\Common\Collections\Collection
     */
    public function getUserRoles()
    {
        return $this->userRoles;
    }

    /**
     * Геттер для массива ролей.
     *
     * @return array An array of Role objects
     */
    public function getRoles()
    {
        return $this->getUserRoles()->map(function ($item) {
            return $item->getName();
        })->toArray();
    }

    /**
     * @param $roleName
     *
     * @return bool
     */
    public function hasRole($roleName)
    {
        return in_array($roleName, $this->getRoles());
    }

}




Я узнал, что загружать роли в UsernamePasswordToken можно с помощью re-authenticate the user
Переопределение токена юзера:
$tokenStorage = $this->get('security.token_storage');
        /** @var $user User */
        $user = $tokenStorage->getToken()->getUser();

        $token = new UsernamePasswordToken(
          $user,
          null,
          'main',
          $user->getRoles()
        );
        $this->get('security.token_storage')->setToken($token);

Если не переопределить токен, $token->getRoles() выдаст лишь роль ROLE_ADMIN (не понимаю откуда она берется, предположительно, это сам симфони присваивает её по дефолту в режиме DEV). А после переопределения, $token->getRoles() выдаёт все роли из БД, доступные юзеру. Что даёт нам возможность в voter-ах делать так:

protected function voteOnAttribute($attribute, $subject, TokenInterface $token)
    {
        // ...

        if ($this->decisionManager->decide($token, array('ROLE_DB_SUPER_ADMIN'))) {
            return true;
        }

                // ...
    }


Так вот, вопрос, где лучше в Simfony3 сделать переопределение токена (см. код выше)? Это нормальная практика? Как я понимаю, делать это переопределение лучше навесив какой-нибудь kernel-listener. Но прежде чем это сделать, хотел узнать - как делать грамотнее.
  • Вопрос задан
  • 450 просмотров
Решения вопроса 1
BoShurik
@BoShurik Куратор тега Symfony
Symfony developer
В секции firewalls.main не указан `provider: main`. Надо указать явно
Ответ написан
Комментировать
Пригласить эксперта
Ответы на вопрос 1
@fattan Автор вопроса
программист
Проблема решилась когда прибегнул к совету @BoShurik
Но заметил такую вещь (мб кому пригодится) - если в БД изменить имя роли, добавить новую, переназначить роль у пользователя и т.п. то $this->get('security.token_storage')->getToken()->getRoles() всё равно выдаст старый список ролей юзера.
Если очистить кэш через консоль, или даже удалить все папки кэша, это не поможет. Помогает ре-аутентификация (разлогиниться, залогиниться). Дело в том что, в конце каждого запроса symfony сериализует (serialize) объект user в $_SESSOIN, а в начале нового запроса десиарилизует (unserialize) объект из сессии. Как я понимаю, с ролями юзера он также поступает.
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Войти через центр авторизации
Похожие вопросы