为什么我在使用此事件订阅者时得到 "An error occurred while loading the web debug toolbar."?
Why do I get "An error occurred while loading the web debug toolbar." when using this Event Subscriber?
我正在创建配置的维护页面。
我创建了一个事件订阅者:
public function onKernelRequest(RequestEvent $event)
{
$maintenance = $this->container->hasParameter('maintenance') ? $this->container->getParameter('maintenance') : false;
$underMaintenanceUntil = $this->container->hasParameter('underMaintenanceUntil') ? $this->container->getParameter('underMaintenanceUntil') : false;
if (!$event->isMasterRequest()){
return;
}
$debug = in_array($this->container->get('kernel')->getEnvironment(), ['test','dev']);
$uri = $event->getRequest()->getRequestUri();
if ($uri == '/login' || $uri == '/logout') {
return;
}
if ($maintenance && !$debug && !$this->container->get('security.authorization_checker')->isGranted('ROLE_ADMIN')) {
$engine = $this->container->get('twig');
$content = $engine->render('pages/maintenance.html.twig', array('underMaintenanceUntil' => $underMaintenanceUntil));
$event->setResponse(new Response($content, 503));
$event->stopPropagation();
}
}
分析器栏不起作用。我得到
An error occurred while loading the web debug toolbar.
在日志中:
[Application] Oct 5 08:24:41 |INFO | REQUES Matched route "_wdt".
method="GET" request_uri="https://localhost:8001/_wdt/914ef7"
route="_wdt"
route_parameters={"_controller":"web_profiler.controller.profiler::toolbarAction","_route":"_wdt","token":"914ef7"}
[Application] Oct 5 08:24:41 |CRITICA| REQUES Uncaught PHP Exception
Symfony\Component\Security\Core\Exception\AuthenticationCredentialsNotFoundException:
"The token storage contains no authentication token. One possible
reason may be that there is no firewall configured for this URL." at
/home/marcin/projects/indali/vendor/symfony/security-core/Authorization/AuthorizationChecker.php
line 52
即使我输入 /login
页面,我也会得到同样的错误。如果它是登录 uri,这个 if ($uri == '/login' || $uri == '/logout') {return;}
不应该阻止不执行进一步的代码吗?
这个 $this->container->get('security.authorization_checker')->isGranted('ROLE_ADMIN')
产生了我的错误,因为在开发防火墙中没有授权令牌。我可以检查令牌是否存在,但为什么我的代码不起作用?
您的代码不起作用,因为探查器是与 /login
或 /logout
.
的主请求分开的请求
分析器栏通过 AJAX 请求加载到另一个 URL。如果您检查您的安全配置,默认值通常是:
dev:
pattern: '^/(_(profiler|wdt)|css|images|js)/'
security: false
Profiler 调用是通过 _profiler
或 _wdt
的调用。因此,您对 login
或 logout
URL 的检查对此根本没有用。它影响主要请求,但不影响分析器栏请求:
一些选项是,从差到好:
检查令牌
正如您提到的,请检查令牌是否不为空,但这可能不会像您预期的那样工作,因为它最终将允许匿名用户在“维护中”访问您的站点。
检查 URL 路径
便宜又简单:根据 dev
模式检查请求路径(或至少根据 _(profiler|wdt)
)。这应该很容易合并到您的代码中,但可以想象,如果您最终添加另一个 non-secured 防火墙,将来可能会出现问题:
if (preg_match('/^\/(logout|login|_(wdt|profiler))/', $uri) {
return;
}
检查 FirewallConfig
请求
如果你想干干净净,你应该在你的事件订阅者中注入 FirewallMap
,并为请求获取防火墙。
一个简单的例子,您需要根据自己的需要进行调整:
use Symfony\Bundle\SecurityBundle\Security;
use Symfony\Component;
class FooSubscriber implements Component\EventDispatcher\EventSubscriberInterface
{
private Security\FirewallMap $firewallMap;
public function __construct(Security\FirewallMap $firewallMap)
{
$this->firewallMap = $firewallMap;
}
public static function getSubscribedEvents(): array
{
return [Component\HttpKernel\KernelEvents::REQUEST => 'onKernelRequest'];
}
public function onKernelRequest(Component\HttpKernel\Event\RequestEvent $event): void
{
if (!$event->isMasterRequest()) {
return;
}
$config = $this->firewallMap->getFirewallConfig($event->getRequest());
if (!$config instanceof Security\FirewallConfig || (!$config->isSecurityEnabled() || $config->allowsAnonymous())) {
return;
}
}
}
由于 FirewallMap
不是 auto-wireable,您需要配置服务以显式注入它:
// services.php
$services->set(FooSubscriber::class)
->args([service('security.firewall.map')]);
或在旧学校 YAML 中:
# services.yaml
services:
App\FooSubscriber:
arguments:
- '@security.firewall.map'
在你的情况下,你似乎正在取消依赖注入并直接检索容器。尽管这是一种不好的做法,您应该尽可能更改它,但使用您当前的代码,您可以简单地从 $this-container->get('security.firewall.map');
获取它
我正在创建配置的维护页面。
我创建了一个事件订阅者:
public function onKernelRequest(RequestEvent $event)
{
$maintenance = $this->container->hasParameter('maintenance') ? $this->container->getParameter('maintenance') : false;
$underMaintenanceUntil = $this->container->hasParameter('underMaintenanceUntil') ? $this->container->getParameter('underMaintenanceUntil') : false;
if (!$event->isMasterRequest()){
return;
}
$debug = in_array($this->container->get('kernel')->getEnvironment(), ['test','dev']);
$uri = $event->getRequest()->getRequestUri();
if ($uri == '/login' || $uri == '/logout') {
return;
}
if ($maintenance && !$debug && !$this->container->get('security.authorization_checker')->isGranted('ROLE_ADMIN')) {
$engine = $this->container->get('twig');
$content = $engine->render('pages/maintenance.html.twig', array('underMaintenanceUntil' => $underMaintenanceUntil));
$event->setResponse(new Response($content, 503));
$event->stopPropagation();
}
}
分析器栏不起作用。我得到
An error occurred while loading the web debug toolbar.
在日志中:
[Application] Oct 5 08:24:41 |INFO | REQUES Matched route "_wdt". method="GET" request_uri="https://localhost:8001/_wdt/914ef7" route="_wdt" route_parameters={"_controller":"web_profiler.controller.profiler::toolbarAction","_route":"_wdt","token":"914ef7"} [Application] Oct 5 08:24:41 |CRITICA| REQUES Uncaught PHP Exception Symfony\Component\Security\Core\Exception\AuthenticationCredentialsNotFoundException: "The token storage contains no authentication token. One possible reason may be that there is no firewall configured for this URL." at /home/marcin/projects/indali/vendor/symfony/security-core/Authorization/AuthorizationChecker.php line 52
即使我输入 /login
页面,我也会得到同样的错误。如果它是登录 uri,这个 if ($uri == '/login' || $uri == '/logout') {return;}
不应该阻止不执行进一步的代码吗?
这个 $this->container->get('security.authorization_checker')->isGranted('ROLE_ADMIN')
产生了我的错误,因为在开发防火墙中没有授权令牌。我可以检查令牌是否存在,但为什么我的代码不起作用?
您的代码不起作用,因为探查器是与 /login
或 /logout
.
分析器栏通过 AJAX 请求加载到另一个 URL。如果您检查您的安全配置,默认值通常是:
dev:
pattern: '^/(_(profiler|wdt)|css|images|js)/'
security: false
Profiler 调用是通过 _profiler
或 _wdt
的调用。因此,您对 login
或 logout
URL 的检查对此根本没有用。它影响主要请求,但不影响分析器栏请求:
一些选项是,从差到好:
检查令牌
正如您提到的,请检查令牌是否不为空,但这可能不会像您预期的那样工作,因为它最终将允许匿名用户在“维护中”访问您的站点。
检查 URL 路径
便宜又简单:根据 dev
模式检查请求路径(或至少根据 _(profiler|wdt)
)。这应该很容易合并到您的代码中,但可以想象,如果您最终添加另一个 non-secured 防火墙,将来可能会出现问题:
if (preg_match('/^\/(logout|login|_(wdt|profiler))/', $uri) {
return;
}
检查 FirewallConfig
请求
如果你想干干净净,你应该在你的事件订阅者中注入 FirewallMap
,并为请求获取防火墙。
一个简单的例子,您需要根据自己的需要进行调整:
use Symfony\Bundle\SecurityBundle\Security;
use Symfony\Component;
class FooSubscriber implements Component\EventDispatcher\EventSubscriberInterface
{
private Security\FirewallMap $firewallMap;
public function __construct(Security\FirewallMap $firewallMap)
{
$this->firewallMap = $firewallMap;
}
public static function getSubscribedEvents(): array
{
return [Component\HttpKernel\KernelEvents::REQUEST => 'onKernelRequest'];
}
public function onKernelRequest(Component\HttpKernel\Event\RequestEvent $event): void
{
if (!$event->isMasterRequest()) {
return;
}
$config = $this->firewallMap->getFirewallConfig($event->getRequest());
if (!$config instanceof Security\FirewallConfig || (!$config->isSecurityEnabled() || $config->allowsAnonymous())) {
return;
}
}
}
由于 FirewallMap
不是 auto-wireable,您需要配置服务以显式注入它:
// services.php
$services->set(FooSubscriber::class)
->args([service('security.firewall.map')]);
或在旧学校 YAML 中:
# services.yaml
services:
App\FooSubscriber:
arguments:
- '@security.firewall.map'
在你的情况下,你似乎正在取消依赖注入并直接检索容器。尽管这是一种不好的做法,您应该尽可能更改它,但使用您当前的代码,您可以简单地从 $this-container->get('security.firewall.map');