2013-10-31 19 views
13

說,例如我授予當前已驗證用戶一個新的角色在一個控制器,像這樣:Symfony 2.3:如何從數據庫刷新經過身份驗證的用戶?

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

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

在接下來的頁面負載,當我搶再次驗證的用戶:

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

他們沒有被賦予這個角色。我猜這是因爲用戶存儲在會話中,需要刷新。

我該怎麼做?

我正在使用FOSUserBundle,如果這有所作爲。

+0

數據庫是否更新? – cheesemacfly

+0

是的數據庫被更新。因此,如果我退出並重新登錄,新角色就會反映出來。 –

+0

我正在使用'if is_granted('ROLE_XYZ')'檢查樹枝模板中的新角色。我改變了這個'如果app.user.hasRole('ROLE_XYZ')'現在它正在工作。奇怪... –

回答

19

試試這個:

$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); 
+0

謝謝!如你所示,訣竅是用新角色替換新安全令牌。 –

+1

我可以確認此解決方案仍然適用於2.6.3 –

+1

仍然適用於2。8 – Brett

10

沒有必要對以前的答案令牌復位。只是,在您的安全配置文件(security.yml,等...),補充一點:

security: 
    always_authenticate_before_granting: true 
+1

如果這是與另一個答案有關的一點,我認爲它會更適合作爲對該答案的評論,而不是自己的答案 – beresfordt

+2

顯然你需要一些聲譽來做到這一點。智能移動所有的周圍。 – Marc

+0

你不知道我很欣賞 – Cavid

8

雖然答案被接受,Symfony的實際上有一個天然的方式來刷新用戶對象。信貸出去給Joeri Timmermans this article

步驟刷新用戶對象:

  1. 讓您的用戶實體實現的接口

的Symfony \分量\安全\核心\用戶\ EquatableInterface

  1. 實現抽象函數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; 
 
}

上述代碼刷新如果添加任何新的角色的用戶對象。同樣的原則也適用於您比較的其他領域。

+0

感謝這!直到現在我還不明白EquatableInterface! – wonzbak

+2

僅供參考:如果你實現了'EquatableInterface',你可能還想添加Symfony通常會做的其他比較(直到你實現了EquatableInterface)。如果您的用戶也實現了AdvancedUserInterface,那麼您可能需要爲'isAccountNonExpired','isAccountNonLocked','isCredentialsNonExpired'和'isEnabled'添加比較。查看https://github.com/symfony/security/blob/v3.1.2/Core/Authentication/Token/AbstractToken.php#L250-L282 – simshaun

2
$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); 
相關問題