Php 检查Symfony中每个控制器中的用户
我有一个属性为“enabled”的用户对象。我希望每个操作在继续之前首先检查用户是否已启用 现在我已经用一个其他控制器都扩展的控制器解决了这个问题,但是使用Php 检查Symfony中每个控制器中的用户,php,symfony,Php,Symfony,我有一个属性为“enabled”的用户对象。我希望每个操作在继续之前首先检查用户是否已启用 现在我已经用一个其他控制器都扩展的控制器解决了这个问题,但是使用setContainer函数捕捉每个控制器的动作感觉非常不舒服 class BaseController扩展控制器{ 公共函数setContainer(ContainerInterface$container=null) { $this->container=$container; $user=$this->getUser(); //将禁用的
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返回响应是一个奇怪的界面。可能需要重新考虑这个。您可以找到basegetUser()函数。您可以根据需要更改它。考虑添加一些细节。也许可以显示如何从Kaln.Read事件中检查控制器类。提示:您不能。他不需要检查控制器类,如果他只需要在某些控制器上工作,他可以以某种方式命名他的路由并推断。谢谢你提醒我,我可以只注入令牌存储。这是我最初的解决方案中缺少的部分。不客气,我建议PapyDanone的方法。我认为简单的逻辑很容易理解。有趣的解决方案,但不够灵活,无法满足我的需要。但是,当一个令牌存储w developer创建了新的控制器,很容易忘记安全检查。在进一步的测试中,如果我只是自定义403错误页面来检查用户是否被禁用,或者如果这是一个常见的403错误,这可能会起作用。我现在有我的答案,但我将添加一个upvote:)
use Sensio\Bundle\FrameworkExtraBundle\Configuration\Security;
/**
* @Security("user.isEnabled()")
*/
class EventController extends Controller
{
// ...
}