检查是否为Symfony2 ACL中的特定用户授予了角色

时间:2014-06-06 09:17:20

标签: symfony acl

我想检查是否为Symfony2中的特定用户授予了角色(而不是已记录的用户)。 我知道我可以通过以下方式为登录用户检查:

$securityContext = $this->get('security.context');

if (false === $securityContext->isGranted('VIEW', $objectIdentity)) {
        //do anything
}

但是,如果我是已登录的用户,并且如果 isGranted 那么我就会检查其他用户

5 个答案:

答案 0 :(得分:6)

" VIEW"是一种许可,而不是一种角色。

检查用户是否有权(无论是角色还是权限)的最佳方法是访问AccessDecisionManager。类似的东西:

$token = new UsernamePasswordToken($user, 'none', 'none', $user->getRoles());
$attributes = is_array($attributes) ? $attributes : array($attributes);
$this->get('security.access.decision_manager')->decide($token, $attributes, $object);

请参阅此处的原始答案:https://stackoverflow.com/a/22380765/971254了解详情。

答案 1 :(得分:5)

您只需创建一个自定义安全上下文,该上下文将获取用户对象并从中生成UserSecurityIdentity。以下是步骤:

在YourApp / AppBundle / Resources / config.yml

中创建新服务
yourapp.security_context:
    class: YourApp\AppBundle\Security\Core\SecurityContext
    arguments: [ @security.acl.provider ]

创建一个自定义安全上下文类,如下所示:

namespace YourApp\AppBundle\Security\Core;

use Symfony\Component\Security\Acl\Model\MutableAclProviderInterface;
use Symfony\Component\Security\Acl\Domain\ObjectIdentity;
use Symfony\Component\Security\Acl\Domain\UserSecurityIdentity;
use Symfony\Component\Security\Acl\Permission\MaskBuilder;

use Symfony\Component\Security\Acl\Exception\AclNotFoundException;
use Symfony\Component\Security\Acl\Exception\NoAceFoundException;

use YourApp\AppBundle\Document\User;

/**
 * Allows ACL checking against a specific user object (regardless of whether that user is logged in or not)
 *
 */
class SecurityContext
{
    public function __construct(MutableAclProviderInterface $aclProvider)
    {
        $this->aclProvider = $aclProvider;
    }

    public function isGranted($mask, $object, User $user)
    {
        $objectIdentity = ObjectIdentity::fromDomainObject($object);
        $securityIdentity = UserSecurityIdentity::fromAccount($user);

        try {
            $acl = $this->aclProvider->findAcl($objectIdentity, array($securityIdentity));
        } catch (AclNotFoundException $e) {
            return false;
        }

        if (!is_int($mask)) {
            $builder = new MaskBuilder;
            $builder->add($mask);

            $mask = $builder->get();
        }

        try {
            return $acl->isGranted(array($mask), array($securityIdentity), false);
        } catch (NoAceFoundException $e) {
            return false;
        }
    }
}

现在您可以根据需要注入该服务,或者从这样的控制器中使用它:

$someUser = $this->findSomeUserFromYourDatabase();

if ($this->get('yourapp.security_context')->isGranted('VIEW', $article, $someUser) {
   // ...
}

答案 2 :(得分:1)

无法通过SecurityContext检查其他用户的角色,因为这将始终保留当前用户的会话令牌。例如,如果您需要检查的用户实现getRoles,则可以通过UserInterface方法实现您的任务。

$otherUser = $this->get('doctrine')->...   // fetch the user

if( $otherUser instanceof \Symfony\Component\Security\Core\User\UserInterface  )
{ 
     $roles = $otherUser->getRoles();

     // your role could be VIEW or ROLE_VIEW, check the $roles array above. 
     if ( in_array( 'VIEW' , $roles ) )
     {
      // do something else
     }
}

如果您的用户实体实施了 FosUserBundle UserInterFace,那么该方法具有专用方法hasRole。在这种情况下,您可以使用单行:

$otherUser = $this->get('doctrine')->...   // fetch the user

if( $otherUser instanceof \FOS\UserBundle\Model\UserInterface  )
{ 
     // your role could be VIEW or ROLE_VIEW, check the proper role names
     if ( $otherUser->hasRole( 'VIEW' ) )
     {
      // do something else
     }
}

答案 3 :(得分:0)

在Sf4中(也许之前不确定),您拥有AuthorizationCheckerInterface,您可以在类似的服务中使用它来检查当前用户的角色:

namespace App\Service;

use Symfony\Component\Security\Core\Authorization\AuthorizationCheckerInterface;
use Symfony\Component\Security\Core\Security;

class MyService
{
    private $authorizationChecker;
    private $security;

    public function __construct(Security $security, AuthorizationCheckerInterface $authorizationChecker)
    {
        $this->authorizationChecker = $authorizationChecker;
        $this->security = $security;
    }

    public function something(): void
    {
        $this->authorizationChecker->isGranted('ROLE_ADMIN', $this->security->getUser());
        [...]
    }
}

它将接受任何有效的用户对象,并且知道角色层次结构。 参考:https://symfony.com/doc/current/components/security/authorization.html

答案 4 :(得分:-3)

DebreczeniAndrás指出的解决方案是正确的。

还可以通过将该逻辑添加为方法来改进用户类。

因此,在我们的用户类(实现UserInterface的用户类)中,我们只需添加此方法:

/**
 * @param string $role
 * @return bool
 */
public function hasRole($role)
{
    if (in_array($role, $this->getRoles())) {
        return true;
    }
    return false;
}

然后我们可以使用:

$someUser->hasRole('SOME_ROLE');