全部設定

首先,我們建立了一個選民:

namespace BBIT\CoreBundle\Security\Authorization\Voter;
 
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
use Symfony\Component\Security\Core\Authorization\Voter\VoterInterface;
 
class EventVoter implements VoterInterface
{
    const VIEW      = 'VIEW';
    const EDIT      = 'EDIT';
    const DELETE    = 'DELETE';
    const CREATE    = 'CREATE';
    const LLIST      = 'LIST';
 
    public function supportsAttribute($attribute)
    {
 
        return in_array($attribute, array(
            self::VIEW,
            self::EDIT,
            self::DELETE,
            self::CREATE,
            self::LLIST,
        ));
    }
 
    public function supportsClass($class)
    {
 
        $supportedClass = 'BBIT\CoreBundle\Entity\SomeEntity';
 
        if (is_string($class)) {
            if ($class === $supportedClass) {
                return true;
            } else {
                return false;
            }
        }
        return $supportedClass === get_class($class) || is_subclass_of(get_class($class), $supportedClass);
    }
 
 
    public function vote(TokenInterface $token, $entity, array $attributes)
    {
        $user = $token->getUser();
 
        if (!is_object($user)) {
            return VoterInterface::ACCESS_DENIED;
        }
 
        if (!$this->supportsClass($entity)) {
            return VoterInterface::ACCESS_ABSTAIN;
        }
 
        $attribute = $attributes[0];
 
        switch($attribute) {
            case self::LLIST:
 
                return VoterInterface::ACCESS_DENIED;
                break;
            case self::VIEW:
 
                return VoterInterface::ACCESS_DENIED;
                break;
            case self::CREATE:
 
                return VoterInterface::ACCESS_DENIED;
                break;
            case self::EDIT:
 
                return VoterInterface::ACCESS_DENIED;
                break;
            case self::DELETE:
 
                return VoterInterface::ACCESS_DENIED;
                break;
        }
 
        return VoterInterface::ACCESS_DENIED;
    }
}

這個選民與 symfony 文件中的預設選民略有不同,其另外的好處是能夠接受一個物件或類名本身作為引數。

其次,我們將建立一個 VoterSecurityhandler,它從 sonata 的 RoleSecurityHandler 擴充套件並覆蓋其中的一部分:

namespace BBIT\CoreBundle\Security\Handler;
 
use Sonata\AdminBundle\Admin\AdminInterface;
use Sonata\AdminBundle\Security\Handler\RoleSecurityHandler;
use Symfony\Component\Security\Core\Exception\AuthenticationCredentialsNotFoundException;
 
class VoterSecurityHandler extends RoleSecurityHandler
{
 
 
    /**
     * {@inheritdoc}
     */
    public function isGranted(AdminInterface $admin, $attributes, $object = null)
    {
        if (!is_array($attributes)) {
            $attributes = array($attributes);
        }
 
        if ($object == $admin) {
            $object = $admin->getClass();
        }
 
        foreach ($attributes as $pos => $attribute) {
            $attributes[$pos] = $attribute;
        }
 
        try {
 
            return $this->securityContext->isGranted($attributes, $object);
        } catch (AuthenticationCredentialsNotFoundException $e) {
            return false;
        } catch (\Exception $e) {
            throw $e;
        }
    }
 
    /**
     * {@inheritdoc}
     */
    public function getBaseRole(AdminInterface $admin)
    {
        return '%s';
    }
 
}

現在我們需要一個服務定義來將此處理程式定義為服務:

services:
    ...
    sonata.admin.security.handler.voter:
        class: BBIT\CoreBundle\Security\Handler\VoterSecurityHandler
        arguments:
            - @security.context
            - [ROLE_SUPER_ADMIN]

現在我們可以告訴 sonata 使用我們的 VoterSecurityHandler:

sonata_admin:
    ...
    security:
        handler: sonata.admin.security.handler.voter

多數民眾贊成在這一點上,奏鳴曲將考慮你的選民,你應該好好去。