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

时间:2023-01-13 06:45:10

I want to check if a role is granted for a specific user in Symfony2 (not the logged user). I know that I can check it for the logged user by:

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

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

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

but if I'm the logged user and I wand to check other user if isGranted ??

但如果我是已登录的用户,并且我的魔杖检查其他用户是否isGranted?

4 个解决方案

#1


6  

The "VIEW" is a permission, not a role.

“VIEW”是权限,而不是角色。

The best way to check if a user has a right (be it a role or permission) would be to access the AccessDecisionManager. Something like:

检查用户是否有权(无论是角色还是权限)的最佳方法是访问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);

See original answer here: https://*.com/a/22380765/971254 for details.

有关详细信息,请参阅原始答案:https://*.com/a/22380765/971254。

#2


5  

You just need to create a custom security context that will take a user object and generate a UserSecurityIdentity out of it. Here are the steps:

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

Create a new service in YourApp/AppBundle/Resources/config.yml

在YourApp / AppBundle / Resources / config.yml中创建新服务

yourapp.security_context:
    class: YourApp\AppBundle\Security\Core\SecurityContext
    arguments: [ @security.acl.provider ]

Create a custom Security Context Class like this:

像这样创建自定义安全上下文类:

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;
        }
    }
}

Now you can inject that service where needed, or use it from a controller like this:

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

$someUser = $this->findSomeUserFromYourDatabase();

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

#3


1  

Checking roles for another user can not be done via the SecurityContext as this will always hold the current user's session token. Your task can be achieved for example via the getRoles method, if the user you need to check implements the UserInterface.

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

$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
     }
}

If your user entity implement the FosUserBundle UserInterFace, that has a dedicated method hasRole. In that case you could use a one-liner:

如果您的用户实体实现了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
     }
}

#4


-3  

The solution pointed by Debreczeni András is the right one.

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

One can also improve the user class by adding that logic as a method.

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

So in our user class (the one which implements the UserInterface) we simply add this method:

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

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

then we are able to use:

然后我们可以使用:

$someUser->hasRole('SOME_ROLE');

#1


6  

The "VIEW" is a permission, not a role.

“VIEW”是权限,而不是角色。

The best way to check if a user has a right (be it a role or permission) would be to access the AccessDecisionManager. Something like:

检查用户是否有权(无论是角色还是权限)的最佳方法是访问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);

See original answer here: https://*.com/a/22380765/971254 for details.

有关详细信息,请参阅原始答案:https://*.com/a/22380765/971254。

#2


5  

You just need to create a custom security context that will take a user object and generate a UserSecurityIdentity out of it. Here are the steps:

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

Create a new service in YourApp/AppBundle/Resources/config.yml

在YourApp / AppBundle / Resources / config.yml中创建新服务

yourapp.security_context:
    class: YourApp\AppBundle\Security\Core\SecurityContext
    arguments: [ @security.acl.provider ]

Create a custom Security Context Class like this:

像这样创建自定义安全上下文类:

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;
        }
    }
}

Now you can inject that service where needed, or use it from a controller like this:

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

$someUser = $this->findSomeUserFromYourDatabase();

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

#3


1  

Checking roles for another user can not be done via the SecurityContext as this will always hold the current user's session token. Your task can be achieved for example via the getRoles method, if the user you need to check implements the UserInterface.

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

$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
     }
}

If your user entity implement the FosUserBundle UserInterFace, that has a dedicated method hasRole. In that case you could use a one-liner:

如果您的用户实体实现了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
     }
}

#4


-3  

The solution pointed by Debreczeni András is the right one.

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

One can also improve the user class by adding that logic as a method.

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

So in our user class (the one which implements the UserInterface) we simply add this method:

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

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

then we are able to use:

然后我们可以使用:

$someUser->hasRole('SOME_ROLE');