Php 检查Symfony中每个控制器中的用户

Php 检查Symfony中每个控制器中的用户,php,symfony,Php,Symfony,我有一个属性为“enabled”的用户对象。我希望每个操作在继续之前首先检查用户是否已启用 现在我已经用一个其他控制器都扩展的控制器解决了这个问题,但是使用setContainer函数捕捉每个控制器的动作感觉非常不舒服 class BaseController扩展控制器{ 公共函数setContainer(ContainerInterface$container=null) { $this->container=$container; $user=$this->getUser(); //将禁用的

我有一个属性为“enabled”的用户对象。我希望每个操作在继续之前首先检查用户是否已启用

现在我已经用一个其他控制器都扩展的控制器解决了这个问题,但是使用
setContainer
函数捕捉每个控制器的动作感觉非常不舒服

class BaseController扩展控制器{
公共函数setContainer(ContainerInterface$container=null)
{
$this->container=$container;
$user=$this->getUser();
//将禁用的用户重定向到信息页面
如果(!$user->isEnabled()&&!$this instanceof InfoController){
返回$this->redirectToRoute('path_to_info');
}
}
我已经尝试使用before过滤器()来构建它,但无法获取用户对象。有什么提示吗

编辑:

这是我的解决方案:
namespace AppBundle\Security;

use AppBundle\Controller\AccessDeniedController;
use AppBundle\Controller\ConfirmController;

use Symfony\Bundle\FrameworkBundle\Routing\Router;
use Symfony\Bundle\TwigBundle\Controller\ExceptionController;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\HttpKernel\Event\FilterControllerEvent;
use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorage;

class UserEnabledListener
{
    private $tokenStorage;
    private $router;

    public function __construct(TokenStorage $tokenStorage, Router $router)
    {
        $this->tokenStorage = $tokenStorage;
        $this->router = $router;
    }

    public function onKernelController(FilterControllerEvent $event)
    {
        $controller = $event->getController();

        /*
         * $controller passed can be either a class or a Closure.
         * This is not usual in Symfony but it may happen.
         * If it is a class, it comes in array format
         */
        if (!is_array($controller)) {
            return;
        }

        $controller = $controller[0];

        // Skip enabled check when:
        // - we are already are the AccessDenied controller, or
        // - user confirms e-mail and becomes enabled again, or
        // - Twig throws error in template
        if ($controller instanceof AccessDeniedController ||
            $controller instanceof ConfirmController ||
            $controller instanceof ExceptionController) {
            return;
        }

        $user = $this->tokenStorage->getToken()->getUser();

        // Show info page when user is disabled
        if (!$user->isEnabled()) {

            $redirectUrl = $this->router->generate('warning');

            $event->setController(function() use ($redirectUrl) {
                return new RedirectResponse($redirectUrl);
            });
        }
    }
}
编辑2:
好的,那么手动检查每个控制器真的很糟糕,因为您将错过来自第三方依赖项的控制器。我将使用安全注释,并在自定义异常控制器或模板中执行进一步的自定义逻辑等。

您还可以覆盖
getuser()
BaseController中也可以运行

/**
 * Get a user from the Security Token Storage.
 *
 * @return mixed
 *
 * @throws \LogicException If SecurityBundle is not available
 *
 * @see TokenInterface::getUser()
 */
protected function getUser()
{
    if (!$this->container->has('security.token_storage')) {
        throw new \LogicException('The SecurityBundle is not registered in your application.');
    }
    if (null === $token = $this->container->get('security.token_storage')->getToken()) {
        return;
    }
    if (!is_object($user = $token->getUser())) {
        // e.g. anonymous authentication
        return;
    }

    // Redirect disabled users to a info page
     if (!$user->isEnabled() && !$this instanceof InfoController) {
         return $this->redirectToRoute('path_to_info');
     }

     return $user;
}
您可以使用侦听任何新请求

您需要注入用户,然后执行验证:

    <service id="my_request_listener" class="Namespace\MyListener">
        <tag name="kernel.event_listener" event="kernel.request" method="onKernelRequest" />
        <argument type="service" id="security.token_storage" />
    </service>

在您的情况下,我将使用
@Security
注释,如果您使用表达式语言,该注释将非常灵活

use Sensio\Bundle\FrameworkExtraBundle\Configuration\Security;

/**
 * @Security("user.isEnabled()")
 */
class EventController extends Controller 
{
    // ...
}
最后,每个控制器文件中只有一行,并且它具有可读性强的优点(新加入项目的开发人员不必在筛选之前检查BaseController的内容或任何潜在内容,就可以立即知道正在发生什么…)


更多相关文档。

如何使用角色
角色用户\u启用
?然后使用防火墙检查此角色显示侦听器代码。要获取用户,只需注入security.token\u存储,然后在需要时从中提取用户。并确保侦听控制器事件。我刚刚查看了您的cod再次强调。绝对不要弄乱setContainer。这可能会带来各种不必要的乐趣。而且我很确定它甚至不起作用。这似乎是一个非常糟糕的主意。它不仅不起作用,而且从getUser返回响应是一个奇怪的界面。可能需要重新考虑这个。您可以找到base
getUser()函数。您可以根据需要更改它。考虑添加一些细节。也许可以显示如何从Kaln.Read事件中检查控制器类。提示:您不能。他不需要检查控制器类,如果他只需要在某些控制器上工作,他可以以某种方式命名他的路由并推断。谢谢你提醒我,我可以只注入令牌存储。这是我最初的解决方案中缺少的部分。不客气,我建议PapyDanone的方法。我认为简单的逻辑很容易理解。有趣的解决方案,但不够灵活,无法满足我的需要。但是,当一个令牌存储w developer创建了新的控制器,很容易忘记安全检查。在进一步的测试中,如果我只是自定义403错误页面来检查用户是否被禁用,或者如果这是一个常见的403错误,这可能会起作用。我现在有我的答案,但我将添加一个upvote:)
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Security;

/**
 * @Security("user.isEnabled()")
 */
class EventController extends Controller 
{
    // ...
}