Php 使用Symfony为未登录用户获取安全令牌
如何为任何用户(而不仅仅是当前登录的用户)获取安全令牌 我希望能够对从数据库获取的用户调用isgrated()Php 使用Symfony为未登录用户获取安全令牌,php,symfony,Php,Symfony,如何为任何用户(而不仅仅是当前登录的用户)获取安全令牌 我希望能够对从数据库获取的用户调用isgrated()isgrated()来自安全服务,因此在不调整会话状态的情况下,很难/没有必要使用它来获取角色 别误会,这绝对有可能。。。这将起作用,例如: public function strangeAction() { // Get your User, however you normally get it $user = $userRepository->find($id
isgrated()
来自安全服务,因此在不调整会话状态的情况下,很难/没有必要使用它来获取角色
别误会,这绝对有可能。。。这将起作用,例如:
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);
}
…但这真的毫无意义
实际上,你不需要代币。更好的方法是在用户实体中添加isgrated()
方法:
// 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->isgrated()
一样,但对于当前登录的用户也是如此。如果您使用Symfony投票者来确定访问权限,这也很好
$token = new UsernamePasswordToken($userObject, 'none', 'main', $userObject->getRoles());
$hasAccess = $this->get('security.access.decision_manager')->decide($token, array('voter'), $optionalObjectToCheckAccessTo);
您是否在数据库中存储用户的角色?谢谢,它起作用了。但是,您的示例中有一个输入错误,我错过了两个小时:您的第一个setToken()使用$previousToken作为参数,而不是$token:DBtw,这对我来说很有意义,因为user->getRoles()不是真正的角色。我真的认为它坏了,但应用程序就是这样工作的,我不能说“嘿,让我们换个安全防火墙吧!”。特别是我实习的最后一天:p这个命题的问题在于它不依赖security.yml中定义的角色层次结构。查找用户是否具有角色与查找用户是否被授予角色(考虑角色层次结构)不同。后者更为困难。我正在寻找这样的解决方案…注意:您可以使用@security.role\u层次结构:getreachableholles服务方法来解析继承的角色