現在ログインしているユーザーだけでなく、任意のユーザーのセキュリティ トークンを取得するにはどうすればよいですか?
データベースから取得したユーザーで 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()
メソッドを User エンティティに追加することです。
// 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);