Symfony: How do I refresh the authenticated user f

2020-01-29 08:36发布

Say for example I grant a new role to the currently authenticated user in a controller, like so:

$em = $this->getDoctrine()->getManager();
$loggedInUser = $this->get('security.context')->getToken()->getUser();
$loggedInUser->addRole('ROLE_XYZ');

$em->persist($loggedInUser);
$em->flush();

On the next page load, when I grab the authenticated user again:

$loggedInUser = $this->get('security.context')->getToken()->getUser();

They are not granted the role. I am guessing this is because the user is stored in the session and needs to be refreshed.

How do I do this?

I am using FOSUserBundle if that makes a difference.

EDIT: This question was originally asked in the context of Symfony version 2.3 but there are answers for more recent versions below as well.

5条回答
看我几分像从前
2楼-- · 2020-01-29 09:07
$user = $this->getUser();
$userManager = $this->get('fos_user.user_manager');
$user->addRole('ROLE_TEACHER');
$userManager->updateUser($user);
$newtoken = new \Symfony\Component\Security\Core\Authentication\Token\UsernamePasswordToken($user,null,'main', $user->getRoles());
$token = $this->get('security.token_storage')->setToken($newtoken);
查看更多
爷的心禁止访问
3楼-- · 2020-01-29 09:17

In Symfony 4

public function somename(ObjectManager $om, TokenStorageInterface $ts)
    {
        $user = $this->getUser();
        if ($user) {
            $user->setRoles(['ROLE_VIP']); //change/update role
            // persist if need
            $om->flush();
            $ts->setToken(
                new PostAuthenticationGuardToken($user, 'main', $user->getRoles())
            );
            //...
        } else {
            //...
        }
    }
查看更多
可以哭但决不认输i
4楼-- · 2020-01-29 09:18

Try this:

$em = $this->getDoctrine()->getManager();
$loggedInUser = $this->get('security.context')->getToken()->getUser();
$loggedInUser->addRole('ROLE_XYZ');

$em->persist($loggedInUser);
$em->flush();

$token = new \Symfony\Component\Security\Core\Authentication\Token\UsernamePasswordToken(
  $loggedInUser,
  null,
  'main',
  $loggedInUser->getRoles()
);

$this->container->get('security.context')->setToken($token);
查看更多
男人必须洒脱
5楼-- · 2020-01-29 09:19

While an answer is accepted, Symfony actually has a native way to refresh the User object. Credit goes out to Joeri Timmermans for this article.

Steps for refreshing the User object:

  1. Make your User entity implement the interface

Symfony\Component\Security\Core\User\EquatableInterface

  1. Implement the abstract function isEqualTo:

public function isEqualTo(UserInterface $user)
{
    if ($user instanceof User) {
        // Check that the roles are the same, in any order
        $isEqual = count($this->getRoles()) == count($user->getRoles());
        if ($isEqual) {
            foreach($this->getRoles() as $role) {
                $isEqual = $isEqual && in_array($role, $user->getRoles());
            }
        }
        return $isEqual;
    }

    return false;
}

The code above refreshes the User object if any new roles are added. The same principle also holds true for other fields you compare.

查看更多
姐就是有狂的资本
6楼-- · 2020-01-29 09:22

There's no need for the token reset in the previous answer. Just, in your security config file (security.yml, etc...), add this:

security:
    always_authenticate_before_granting: true
查看更多
登录 后发表回答