如何使用Symfony2中的AccessDecisionManager来授权任意用户? [英] How to use the AccessDecisionManager in Symfony2 for authorization of arbitrary users?

查看:97
本文介绍了如何使用Symfony2中的AccessDecisionManager来授权任意用户?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想能够验证是否将属性(角色)授予在Symfony2中实现UserInterface的任意对象.这可能吗?

I'd like to be able to verify whether or not attributes (roles) are granted to any arbitrary object implementing UserInterface in Symfony2. Is this possible?

UserInterface->getRoles()不适合我的需要,因为它没有考虑到角色层次结构,并且我不想在该部门重新发明轮子,这就是为什么我想在以下情况下使用Access Decision Manager:可能.

UserInterface->getRoles() is not suitable for my needs because it does not take the role hierarchy into account, and I'd rather not reinvent the wheel in that department, which is why I'd like to use the Access Decision Manager if possible.

谢谢.

以下是我对Olivier解决方案的回应:

您可以将security.context服务与isGranted方法一起使用.您可以传递第二个参数,即您的对象.

You can use the security.context service with the isGranted method. You can pass a second argument which is your object.

$user = new Core\Model\User();
var_dump($user->getRoles(), $this->get('security.context')->isGranted('ROLE_ADMIN', $user));

输出:

array (size=1)
  0 => string 'ROLE_USER' (length=9)

boolean true

我的角色层次结构:

role_hierarchy:
    ROLE_USER:          ~
    ROLE_VERIFIED_USER: [ROLE_USER]
    ROLE_ADMIN:         [ROLE_VERIFIED_USER]
    ROLE_SUPERADMIN:    [ROLE_ADMIN, ROLE_ALLOWED_TO_SWITCH]
    ROLE_ALLOWED_TO_SWITCH: ~

我的UserInterface->getRoles()方法:

public function getRoles()
{
    $roles = [$this->isVerified() ? 'ROLE_VERIFIED_USER' : 'ROLE_USER'];

    /**
     * @var UserSecurityRole $userSecurityRole
     */
    foreach ($this->getUserSecurityRoles() as $userSecurityRole) {
        $roles[] = $userSecurityRole->getRole();
    }

    return $roles;
}

必须明确分配

ROLE_ADMIN,但是isGranted('ROLE_ADMIN', $user)返回TRUE,即使该用户是刚刚创建的,并且除了当前ROLE_USER之外没有分配任何角色,只要当前已登录用户被授予ROLE_ADMIN .这使我相信,只是忽略了isGranted()的第二个参数,而是使用了SecurityContext提供给AccessDecisionManager->decide()Token.

ROLE_ADMIN must be explicitly assigned, yet isGranted('ROLE_ADMIN', $user) returns TRUE even if the user was just created and has not been assigned any roles other than the default ROLE_USER, as long as the currently logged in user is granted ROLE_ADMIN. This leads me to believe the 2nd argument to isGranted() is just ignored and that the Token provided to AccessDecisionManager->decide() by the SecurityContext is used instead.

如果这是一个错误,我将提交报告,但也许我还在做错什么?

If this is a bug I'll submit a report, but maybe I'm still doing something wrong?

推荐答案

RoleVoter忽略了从SecurityContext->isGranted()传递的$ object.这导致RoleHierarchyVoterToken中提取角色,而不是提供的UserInterface $ object(如果存在),因此我不得不找到另一条路线.

RoleVoter disregards the $object passed through from SecurityContext->isGranted(). This results in the RoleHierarchyVoter extracting roles from the Token instead of a provided UserInterface $object (if exists), so I had to find a different route.

也许有更好的方法可以解决此问题,如果我想知道的话,但这是我想出的解决方案:

Maybe there is a better way to go about this and if there is I'd sure like to know, but this is the solution I came up with:

首先,我在User类中实现了ContainerAwareInterface,以便可以从其中访问安全组件:

First I implemented ContainerAwareInterface in my User class so I could access the security component from within it:

final class User implements AdvancedUserInterface, ContainerAwareInterface
{
    // ...

    /**
     * @var ContainerInterface
     */
    private $container;

    // ...

    public function setContainer(ContainerInterface $container = null)
    {
        if (null === $container) {
            throw new \Exception('First argument to User->setContainer() must be an instance of ContainerInterface');
        }

        $this->container = $container;
    }

    // ...
}

然后我定义了hasRole()方法:

/**
 * @param string|\Symfony\Component\Security\Core\Role\RoleInterface $roleToCheck
 * @return bool
 * @throws \InvalidArgumentException
 */
public function hasRole($roleToCheck)
{
    if (!is_string($roleToCheck)) {
        if (!($roleToCheck instanceof \Symfony\Component\Security\Core\Role\RoleInterface)) {
            throw new \InvalidArgumentException('First argument expects a string or instance of RoleInterface');
        }
        $roleToCheck = $roleToCheck->getRole();
    }

    /**
     * @var \Symfony\Component\Security\Core\SecurityContext $thisSecurityContext
     */
    $thisSecurityContext = $this->container->get('security.context');
    $clientUser = $thisSecurityContext->getToken()->getUser();

    // determine if we're checking a role on the currently authenticated client user
    if ($this->equals($clientUser)) {
        // we are, so use the AccessDecisionManager and voter system instead
        return $thisSecurityContext->isGranted($roleToCheck);
    }

    /**
     * @var \Symfony\Component\Security\Core\Role\RoleHierarchy $thisRoleHierarchy
     */
    $thisRoleHierarchy = $this->container->get('security.role_hierarchy');
    $grantedRoles = $thisRoleHierarchy->getReachableRoles($this->getRoles());

    foreach ($grantedRoles as $grantedRole) {
        if ($roleToCheck === $grantedRole->getRole()) {
            return TRUE;
        }
    }

    return FALSE;
}

从控制器:

$user = new User();
$user->setContainer($this->container);

var_dump($user->hasRole('ROLE_ADMIN'));
var_dump($this->get('security.context')->isGranted('ROLE_ADMIN'));
var_dump($this->get('security.context')->isGranted('ROLE_ADMIN', $user));

$user->addUserSecurityRole('ROLE_ADMIN');
var_dump($user->hasRole('ROLE_ADMIN'));

输出:

boolean false
boolean true
boolean true

boolean true

尽管它不涉及AccessDecisionManager或已注册的选民(除非所测试的实例是当前经过身份验证的用户),但它足以满足我的需要,因为我只需要确定给定用户是否具有特定角色即可

Although it does not involve the AccessDecisionManager or registered voters (unless the instance being tested is the currently authenticated user), it is sufficient for my needs as I just need to ascertain whether or not a given user has a particular role.

这篇关于如何使用Symfony2中的AccessDecisionManager来授权任意用户?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆