Symfony2 自定义选民角色层次结构 [英] Symfony2 Custom Voter Role Hierarchy

查看:23
本文介绍了Symfony2 自定义选民角色层次结构的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试创建一个自定义投票者来检查对实体的访问以进行特定操作.所以这个逻辑运行良好.但是,如果用户是该实体的所有者",或者他们是管理员,我将允许执行一些操作.

I'm trying to create a custom voter to check access on entities for specific actions. So the logic for that is working fine. But then I have some actions that are allowed if the user is either the "owner" of that entity, or they are an admin.

但是,我不能只检查用户的角色,因为我正在查看角色层次结构.文档中的示例仅使用 in_array,但这不起作用 (http://symfony.com/doc/current/best_practices/security.html)

However, I can't just check the ROLE of the user because I'm looking at the role hierarchy. The example in the docs for this just uses in_array, but that won't work (http://symfony.com/doc/current/best_practices/security.html)

我的选民就是这样(为了清楚起见缩短了).我已经尝试注入安全上下文(或者特别是 2.6 中的 AuthorizationCheckerInterface),但是由于这是一个投票者,所以它具有循环依赖.

My voter is like this (shortened for clarity). I've tried injecting the security context (or specifically AuthorizationCheckerInterface in 2.6), but that has a circular dependency since this is a voter.

<?php
// ...
class ApplicationVoter extends AbstractVoter
{
    const VIEW = 'view';

    /**
     * @var AuthorizationCheckerInterface 
     */
    private $security;

    /*public function __construct(AuthorizationCheckerInterface $security)
    {
        $this->security = $security;
    }*/

    /**
     * {@inheritdoc}
     */
    protected function getSupportedAttributes()
    {
        return array(
            self::VIEW
        );
    }

    /**
     * {@inheritdoc}
     */
    protected function getSupportedClasses()
    {
        return array('Study\MainBundle\Entity\Application');
    }

    /**
     * {@inheritdoc}
     */
    protected function isGranted($attribute, $application, $user = null)
    {
        if (!$user instanceof UserInterface) {
            return false;
        }

        if ($attribute === self::VIEW) {
            return $this->canView($application, $user);
        }

        return false;
    }

    /**
     * Can view own application if not deleted
     * Admin can view if submitted
     * 
     * @param \Study\MainBundle\Entity\Application $application
     * @param \Study\MainBundle\Entity\User $user
     * 
     * @return boolean
     */
    protected function canView(Application $application, User $user)
    {
        return ($application->isOwner($user) && !$application->isDeleted())
            || (!$application->isHiddenToAdmin() && $this->security->isGranted('ROLE_ADMIN_RO'));
    }
}

我想在这里只使用内置的 RoleHiearchyVoter,但它是一项非公共服务.有什么解决办法吗?如果可能的话,我想避免重复框架代码或使我的角色比字符串更复杂.

I'd like to just use the built-in RoleHiearchyVoter here, but it's a non-public service. Is there some solution for this? I'd like to avoid duplicating framework code or making my roles more complicated than just strings if possible.

注入整个容器有效,但不是我理想的解决方案.这是我可以从选民那里访问内置层次结构的唯一方法吗?

Injecting the whole container works, but isn't my ideal solution. Is that the only way I can access the built-in hierarchy from a voter?

推荐答案

有一项名为 security.role_hierarchy 的服务,其中包含您需要的信息.这基本上是安全上下文检查角色的方式.需要几行包装器代码,但还不错.

There is a service called security.role_hierarchy which has the info you need. It's basically how the security context checks for roles. Need a few lines of wrapper code but it's not too bad.

# Need this because the service is not public
# http://symfony.com/doc/current/components/dependency_injection/advanced.html
cerad_core__role_hierarchy:
    alias: security.role_hierarchy

cerad_game__game_official__voter:
    class:  Cerad\Bundle\GameBundle\Action\GameOfficial\GameOfficialVoter
    public: false
    arguments:
      - '@cerad_core__role_hierarchy'
    tags:
       - { name: security.voter } 

选民类别:

class GameOfficialVoter implements VoterInterface
{    
    public function __construct($roleHierarchy)
    {  
        $this->roleHierarchy = $roleHierarchy;
    }

    protected function hasRole($token,$targetRole)
    {
        $reachableRoles = $this->roleHierarchy->getReachableRoles($token->getRoles());
        foreach($reachableRoles as $role)
        {
            if ($role->getRole() == $targetRole) return true;
        }
        return false;
    }

    protected function canViewOfficialName($official,$token)
    {    
         // Pending is the only one protected against for now
         if ($official->getAssignState() != 'Pending') return $this->accessGranted;

         // Assignors can always see
         if ($this->hasRole($token,'ROLE_ASSIGNOR')) return $this->accessGranted;

         return $this->accessDenied;
    }
}

这篇关于Symfony2 自定义选民角色层次结构的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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