Получить токен безопасности для незарегистрированного пользователя с помощью Symfony

Как я могу получить токен безопасности для любого пользователя, а не только того, кто в настоящий момент входит в систему?

Я хотел бы иметь возможность вызвать isGranted () для пользователя, извлеченного из базы данных

isGranted() поступает из службы безопасности, поэтому было бы сложно / не нужно использовать это для получения Ролей без корректировки состояния сеанса.

Не поймите меня неправильно, это определенно возможно … Это будет работать, например:

 public function strangeAction() { // Get your User, however you normally get it $user = $userRepository->find($id); // Save the current token so you can put it back later $previousToken = $this->get("security.context")->getToken(); // Create a new token $token = new UsernamePasswordToken($user, null, "main", $user->getRoles()); // Update the security context with the new token $this->get("security.context")->setToken($token); // Now you have access to isGranted() if ($this->get("security.context")->isGranted("ROLE_SOMETHING")) { /* Do something here */ } // Don't forget to reset the token! $this->get("security.context")->setToken($previousToken); } 

… но это действительно бессмысленно.

На самом деле вам не нужен токен. Гораздо лучший способ сделать это – добавить метод isGranted() в свой пользовательский объект:

 // Namespace\YourBundle\Entity\User.php class User { ... public function isGranted($role) { return in_array($role, $this->getRoles()); } ... } 

Теперь вы можете получить эти роли в своих контроллерах:

 public function notSoStrangeAction() { // Get your User, however you normally get it $user = $userRepository->find($id); // Find out if that User has a Role associated to it if ($user->isGranted("ROLE_SOMETHING")) { /* Do something here */ } } 

У меня были те же требования некоторое время назад. Поэтому я реализовал это сам. Поскольку вам требуется информация о иерархии из контейнера, не рекомендуется распространять пользовательский объект с этой функциональностью.

 // first check if the role is inside the user roles of the user // if not then check for each user role if it is a master role of the check role public function isGranted($user, $checkrole){ $userroles = $user->getRoles(); if (in_array($checkrole, $userroles)){return true;} foreach ($userroles as $userrole){ if ($this->roleOwnsRole($userrole, $checkrole)){return true;} } return false; } // recursively loop over the subroles of the master to check if any of them are // the suggested slave role. If yes then the masterrole is a master and has // the same grants as the slave. private function roleOwnsRole($masterRole, $slaveRole, $checkvalidityroles=true, $hierarchy=null) { if ($hierarchy===null){$hierarchy = $this->container->getParameter('security.role_hierarchy.roles');} if ($masterRole === $slaveRole){ return false; } if($checkvalidityroles && (!array_key_exists($masterRole, $hierarchy) || !array_key_exists($slaveRole, $hierarchy))){ return false; } $masterroles = $hierarchy[$masterRole]; if(in_array($slaveRole, $masterroles)){ return true; }else{ foreach($masterroles as $masterrolerec){ if ($this->roleOwnsRole($masterrolerec, $slaveRole, false, $hierarchy)){return true;} } return false; } } 

Я думаю, что лучший способ – вызвать AccessDecisionManager вручную – например, $securityContext->isGranted() , но для текущего пользователя. Это тоже хорошо, если вы используете Symfony Voters для определения доступа.

 $token = new UsernamePasswordToken($userObject, 'none', 'main', $userObject->getRoles()); $hasAccess = $this->get('security.access.decision_manager')->decide($token, array('voter'), $optionalObjectToCheckAccessTo);