【问题标题】:How to retrieve full role hierarchy in Symfony如何在 Symfony 中检索完整的角色层次结构
【发布时间】:2012-01-19 14:50:53
【问题描述】:

我正在使用 symfony2 角色层次结构,它运行良好,但为了执行一些更改,我必须检索在我的 security.yml 中设置的 role_hierarchy

role_hierarchy:
ROLE_USER: [ROLE_ACCESS_USER, ROLE_ACCESS_DATA, ROLE_ACCESS_PRODUCT]

使用getRoles() 只返回ROLE_USER,我怎么能在我的代码中知道ROLE_USER 是用ROLE_ACCESS_USER, ROLE_ACCESS_DATA, ROLE_ACCESS_PRODUCT 创建的?

感谢您的帮助。

【问题讨论】:

  • 你需要它做什么?
  • 我的“用户”(ROLE_USER)有一组默认的角色,我想允许管理员只给他特定的角色,例如只有 ROLE_ACCESS_DATA。我想通过一个显示所有现有角色的界面来做到这一点。

标签: symfony


【解决方案1】:

您可以从容器中获取层次结构:

$container->getParameter('security.role_hierarchy.roles')

【讨论】:

    【解决方案2】:

    启用自动连接后,您还可以直接注入填充了全局角色层次结构的RoleHierarchy 对象。 只需使用依赖注入RoleHierarchyInterface注入您的控制器或服务:

    use Symfony\Component\Security\Core\Role\RoleHierarchyInterface;
    
    public function __construct(RoleHierarchyInterface $roleHierarchy)
    {
        $this->roleHierarchy = $roleHierarchy;
    }
    

    注意:这也允许您在 RoleHierarchy 对象上调用 getReachableRoles(),这在您的情况下可能很有用:

    use Symfony\Component\Security\Core\Role\Role;
    
    $this->roleHierarchy->getReachableRoles([new Role('ROLE_USER')])
    

    从 Symfony4 开始,您必须在 config/services.yml 中添加 security.role_hierarchy 的别名,方法是添加以下行:

    services:
        # creating alias for RoleHierarchyInterface
        Symfony\Component\Security\Core\Role\RoleHierarchyInterface: '@security.role_hierarchy'
    

    【讨论】:

    【解决方案3】:

    Symfony 5 回答

    namespace App\Controller;
    
    ...
    use Symfony\Component\Security\Core\Role\RoleHierarchyInterface;
    use Symfony\Component\Security\Core\Role\RoleHierarchy;
    
    class UserController extends AbstractController
    {
        private $roleHierarchy;
    
        /**
         * @Route("/users", name="users")
         */
        public function usersIndex(RoleHierarchyInterface $roleHierarchy)
        {
            $this->roleHierarchy = $roleHierarchy;
    
            // your user service or your Doctrine code here
            $users = ...
    
            foreach ($users as $user) {
                if ($this->isGranted($user, 'ROLE_SUPER_ADMIN')) {
                    ...
                }
            }
            ...
        }
    
        private function isGranted(User $user, string $role): bool 
        {
            $reachableRoles = $this->roleHierarchy->getReachableRoleNames($user->getRoles());
    
            foreach ($reachableRoles as $reachableRole) {
                if ($reachableRole === $role) {
                    return true;
                }
            }
    
            return false;
        }
    }
    

    注意:为了简单起见,我将所有内容都放在了控制器中,但我当然建议将角色管理代码移动到您自己的专用角色服务中。

    【讨论】:

    • $roles = $roleHierarchy->getReachableRoleNames($user->getRoles()); 未在 usersIndex() 方法中使用 - 是被遗忘的语句吗?
    • @long 谢谢,不知道为什么会出现在这里。固定:)
    • 如何在控制器中不提及而用扩展逻辑覆盖RoleHierarchy接口?
    【解决方案4】:

    为了正确表示您的角色,您需要递归。角色可以扩展其他角色。

    这里是一个例子:https://stackoverflow.com/a/36900807/3635680

    【讨论】:

    • 请在您的回答中引用相关文字。不建议发布仅链接的答案(即使链接导致 Stack Overflow)。
    【解决方案5】:

    security.role_hierarchy.roles 是security.yml中定义的所有安全角色

    如果您想包含 Sonata 管理员角色,您可以检查 SonataUserBundle\Form\Type\SecurityRolesType 中的代码

    foreach ($this->pool->getAdminServiceIds() as $id) {
                try {
                    $admin = $this->pool->getInstance($id);
                } catch (\Exception $e) {
                    continue;
                }
    
                $securityHandler = $admin->getSecurityHandler();
    
                foreach ($securityHandler->buildSecurityInformation($admin) as $role => $acls) {
                    $roles[$role] = $role;
                }
            }
    

    【讨论】:

      猜你喜欢
      • 2014-06-17
      • 2010-11-19
      • 2020-08-14
      • 2012-06-16
      • 1970-01-01
      • 2016-10-29
      • 2020-10-09
      • 2017-12-27
      • 1970-01-01
      相关资源
      最近更新 更多