如何在 Symfony 自定义选民中使用 dump() 或 dd()?

How to use dump() or dd() inside a Symfony Custom Voter?

我遵循了 symfony、api-platform 和几个 Whosebug 示例中的几个示例,但无济于事。我不知道是我做错了什么还是我不理解选民和角色的概念。当我尝试访问端点时,它抛出 只有拥有权限的用户才能查看仪表板。

在services.yaml

app.user_permission:
        class: App\Security\SecurityVoter
        arguments: ['@security.access.decision_manager']
        tags:
            - { name: security.voter}

我创建了一个自定义投票器来使用。这里我做了一些修改,删除了一些东西以采用我在 Whosebug 上看到的示例

use App\Entity\Product;
use Symfony\Component\Security\Core\Security;
use Symfony\Component\Security\Core\User\UserInterface;
use Symfony\Component\Security\Core\Authorization\Voter\Voter;
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;
use Symfony\Component\Security\Core\Authorization\AccessDecisionManagerInterface;


class SecurityVoter extends Voter {
        
        private $decisionManager;
        const VIEW = 'view';
        const EDIT = 'edit';

        
        public function __construct (AccessDecisionManagerInterface $decisionManager) {
            $this->decisionManager = $decisionManager;
        }
        

        protected function supports($attribute, $subject): bool {
            // if the attribute isn't one we support, return false
            if (!in_array($attribute, [self::VIEW, self::EDIT])) {
                return false;
            }
            
          return true;
           
        }
        /**
         * @param string $attribute
         * @param TokenInterface $token
         * @return bool
         */
        protected function voteOnAttribute($attribute, $object, TokenInterface $token): bool {
            $user = $token->getUser();
            
            if (!$user instanceof UserInterface) {
                // the user must be logged in; if not, deny access
                return false;
            }

            
           // check ROLE_USER 
            if ($this->security->isGranted('ROLE_USER')) {
                return true;
            }
            switch ($attribute) {
                case self::VIEW:
                    if($this->decisionManager->decide($token, ['ROLE_USER'])) {
                        return true;
                    }
                break;
                case self::EDIT:
                    if($this->decisionManager->decide($token, ['ROLE_USER'])) {
                        return true;
                    }
                break;

            }
            
            throw new \LogicException('This code should not be reached!');
        }
        
     
}

在我的实体中,我定义了这样的东西。

#[ApiResource(
    attributes: ["security" => "is_granted('ROLE_USER')"],
    collectionOperations: [
        "get",
        "post" => [
            "security_post_denormalize" => "is_granted('ROLE_USER)",
            "security_message" => "Only user with permission can create a dashboard.",
        ],
    ],
    itemOperations: [
        "get" => [ "security" => "is_granted('VIEW') " , "security_message" => "Only user with permission can view dashboard."],
        "put" => [ "security" => "is_granted('EDIT')", "security_message" => "Only user with permission can edit dashboard."],
    ],
)]

我目前使用的是 Symfony 5.4.7,我已经尝试使用示例代码。似乎没有任何效果。我必须使用 dd()dump(),控制台或分析器上没有打印任何内容。我已经使用了 loggerInterface(也许我没有正确使用),但我没有看到任何输出到 var.

你比你想象的要近。您不需要 使用 Symfony\Component\Security\Core\Authorization\AccessDecisionManagerInterface。您可以按如下方式使用安全 class。

use App\Entity\Product;
use Symfony\Component\Security\Core\Security;
use Symfony\Component\Security\Core\User\UserInterface;
use Symfony\Component\Security\Core\Authorization\Voter\Voter;
use Symfony\Component\Security\Core\Authentication\Token\TokenInterface;


class SecurityVoter extends Voter {
        
        private $security;
        const VIEW = 'view';
        const EDIT = 'edit';

        
        public function __construct ( Security $security) {
            $this->security = $security;
        }
        

        protected function supports($attribute, $subject): bool {
            // if the attribute isn't one we support, return false
            $supportsAttribute = in_array($attribute, ['VIEW', 'EDIT']);
            $supportsSubject = $subject instanceof WorkshopSession;
    
            return $supportsAttribute && $supportsSubject;
           
        }
        /**
         * @param string $attribute
         * @param Product $product
         * @param TokenInterface $token
         * @return bool
         */
        protected function voteOnAttribute($attribute, $subject, TokenInterface $token): bool {
            $user = $token->getUser();
            
            if (!$user instanceof UserInterface) {
                // the user must be logged in; if not, deny access
                return false;
            }

         
           
            dd($user);

           // check ROLE_USER 
            if ($this->security->isGranted('ROLE_USER')) {
                return true;
            }
            switch ($attribute) {
                case self::VIEW:
                    if($this->security->isGranted('ROLE_USER')) {
                        return true;
                    }
                break;
                case self::EDIT:
                    if($this->security->isGranted('ROLE_USER')) {
                        return true;
                    }
                break;

            }
            
            throw new \LogicException('This code should not be reached!');
        }
        
     
}

同时,您不需要为此配置服务。

要将选民注入安全层,您必须将其声明为服务并用 security.voter 标记。但如果您使用的是默认 services.yaml 配置,系统会自动为您完成!

在您的实体中

#[ApiResource(
    attributes: ["security" => "is_granted('ROLE_USER')"],
    collectionOperations: [
        "get",
        "post" => [
            "security_post_denormalize" => "is_granted('ROLE_USER')",
            "security_message" => "Only user with permission can create a dashboard.",
        ],
    ],
    itemOperations: [
        "get" => [ "security" => "is_granted('VIEW', object) " ],
        "put" => [ "security" => "is_granted('EDIT')", "security_message" => "Only user with permission can edit dashboard."],
    ],
)]

您也可以阅读此内容以供参考 - API Platform

注意:您可以使用 dd() - 例如dd($用户);