将 Voter 自动应用于控制器中的多个方法

Applying Voter automatically to several methods in a controller

我有一个投票器检查用户是否可以编辑文档,规则是用户拥有文档或用户是超级管理员,要检查文档的所有权,首先必须获取文档实体。这个我没有遇到任何问题。

不过好像还得补充一句: $this->denyAccessUnlessGranted('edit', $doc); 我的控制器中有大约 7 个方法,是否有更有效的方法?

我考虑过使用内核事件,但是将此检查放入事件订阅者中并没有太大作用,因为我看不出有任何方法可以影响进一步的代码执行。如果我抛出未捕获的异常,整个 Symfony 就会崩溃。无论我做什么,被调用的方法都会被执行……但是我还不如编辑每个方法。 我不想到处重复这段代码,但似乎我没有其他选择。

这将取决于您从哪里获得 $doc。您可以将 @Security 注释(或 @IsGranted("do-stuff-with-doc"))放在 class 本身上,以允许或拒绝访问其中的所有操作(这确实假定只有您想要的 7 个操作保护都在同一个 class).

通过 voter 检查当前用户对名为 "do-stuff-with-doc" 的权限的访问权限,因为这也是一项服务,它可以访问您要注入的所有其他服务,以及将要注入到适当操作中的 $request(通过 RequestStack $reqstack; $currRequest = $reqstack->getCurrentRequest();)。在当前请求中是操作的参数,它要么有 $doc,要么有足够的信息,你可能会得到它。

通过该服务或您可以自动连接(或手动定义以注入)到选民中的其他服务,由您决定用户如何或为什么可以访问任何内容。

class DoDocStuffVoter extends Voter
{
    public function __construct(RequestStack $reqStack)
    {
        $this->reqStack = $reqStack;
        // and other services you want to add
    }

    public function supports($attribute, $subject)
    {
        return $attribute === 'do-stuff-with-doc';
    }

    protected function voteOnAttribute($attribute, $object, TokenInterface $token): bool
    {
        $user = $token->getUser(); 
        $request = $this->reqStack->getCurrentRequest();

        dump($user, $request);
        die;

        // does someone with this request get access to doc?
        return $this->userHasAccessToDoc($user, $request);  
    }
}