我正在研究Symfony 3.4项目,并且一直面临着一个奇怪的问题。 Web调试工具栏无法加载,而是出现错误"加载Web调试工具栏时出错。打开Web Profiler。"这是截图
当我点击打开网页探查器链接时,它会转到另一个异常页面。这是它的截图
因此,经过数小时的调试后,我能够发现问题出在了 自定义监听器。它在我的services.yml中注册如下:
services:
language.kernel_request_listener:
class: TraceBundle\Listeners\LanguageListener
arguments:
- "@service_container"
tags:
- { name: kernel.event_listener, event: kernel.request, method: setLocale }
这是LanguageListener.php:
<?php
namespace TraceBundle\Listeners;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Symfony\Component\HttpKernel\Event\GetResponseEvent;
use Symfony\Component\HttpKernel\HttpKernelInterface;
class LanguageListener{
private $token_storage;
private $securityContext;
private $container;
public function __construct(ContainerInterface $containerInterface)
{
$this->container = $containerInterface;
$this->securityContext = $this->container->get('security.authorization_checker');
$this->token_storage = $this->container->get('security.token_storage');
}
public function setLocale(GetResponseEvent $event)
{
if (HttpKernelInterface::MASTER_REQUEST !== $event->getRequestType()) {
return;
}
if ($this->securityContext->isGranted('IS_AUTHENTICATED_REMEMBERED')) {
$user = $this->token_storage->getToken()->getUser();
$userLocale = $user->getTenant()->getLanguage()->getValue();
$tenantid = $this->container->get('tenant_manager')->getTenantId($user);
$request = $event->getRequest();
$request->attributes->set('tenantid', $tenantid);
if ($userLocale) {
$request->setLocale($userLocale);
$translator = $this->container->get('translator');
$translator->setLocale($userLocale);
}
}
}
}
现在我评论以下几行:
if ($this->securityContext->isGranted('IS_AUTHENTICATED_REMEMBERED')) {
$user = $this->token_storage->getToken()->getUser();
$userLocale = $user->getTenant()->getLanguage()->getValue();
$tenantid = $this->container->get('tenant_manager')->getTenantId($user);
$request = $event->getRequest();
$request->attributes->set('tenantid', $tenantid);
if ($userLocale) {
$request->setLocale($userLocale);
$translator = $this->container->get('translator');
$translator->setLocale($userLocale);
}
错误消失,探查器按预期加载。
我已经在每一行之后尝试var_dump()
并且所有值似乎都很好。服务tenant_manager工作正常以及翻译服务。我在这里错过了什么?如果您需要更多代码,请与我们联系。
提前致谢!
编辑:这里要求的是我的security.yml:
security:
# https://symfony.com/doc/current/security.html#b-configuring-how-users-are-loaded
providers:
in_memory:
memory: ~
fos_userbundle:
id: fos_user.user_provider.username
firewalls:
# disables authentication for assets and the profiler, adapt it according to your needs
dev:
pattern: ^/(_(profiler|wdt)|css|images|js)/
security: false
main:
pattern: ^/
form_login:
success_handler: authentication.handler.login_success_handler
provider: fos_userbundle
csrf_token_generator: security.csrf.token_manager
# logout: true
logout:
path: /logout
target: /login
anonymous: true
js_router:
pattern: ^/(js\/routing)
security: false
encoders:
FOS\UserBundle\Model\UserInterface: bcrypt
role_hierarchy:
ROLE_ADMIN: ROLE_USER
ROLE_SUPER_ADMIN: ROLE_ADMIN
access_control:
- { path: ^/login$, role: IS_AUTHENTICATED_ANONYMOUSLY }
- { path: ^/dashboard, role: ROLE_ADMIN }
- { path: ^/campaigns, role: ROLE_ADMIN }
- { path: ^/dashboard, role: ROLE_ADMIN }
- { path: ^/lives, role: ROLE_ADMIN }
- { path: ^/colleagues, role: ROLE_ADMIN }
- { path: ^/addcolleague, role: ROLE_ADMIN }
- { path: ^/adminpage, role: ROLE_ADMIN }
- { path: ^/test, role: ROLE_ADMIN }
- { path: ^/register, role: IS_AUTHENTICATED_ANONYMOUSLY }
- { path: ^/resetting, role: IS_AUTHENTICATED_ANONYMOUSLY }
- { path: ^/admin/, role: ROLE_ADMIN }
答案 0 :(得分:1)
我用你的代码做了一些实验,发现了这个:
删除这些行解决了这个问题:
dev:
pattern: ^/(_(profiler|wdt)|css|images|js)/
security: false
也用这些替换它们有帮助:
dev:
pattern: ^/(_(profiler|wdt)|css|images|js)/
anonymous: true
因此,我可以得出结论security: false
导致在幕后将安全令牌设置为null
。
到目前为止,我没有找到这种机制(会继续尝试),所以如果有任何帮助,我将不胜感激。
另一种解决方案是在侦听器内部检查令牌是否为空:
if (null !== $this->token_storage->getToken()
&& $this->securityContext->isGranted('IS_AUTHENTICATED_REMEMBERED')) {
...
}
但是它使你的代码关心你的dev config(开发防火墙)造成的情况,所以我认为这不是最好的方法。
欢迎任何评论/补充。
答案 1 :(得分:1)
使用带有TokenStorageInterface的自定义侦听器时,我遇到了完全相同的问题。
这是我的侦听器代码的缩小版本:
class DatabaseUserAuthenticationListener {
private $authToken;
public function __construct(TokenStorageInterface $tokenStorage) {
if ($tokenStorage->getToken()) {
$this->authToken = $tokenStorage->getToken();
}
}
public function onKernelController(FilterControllerEvent $event) {
if ($this->authToken) {
$this->authToken->setAttribute("blah", true);
}
}
}
就我而言,违规行是$this->authToken->setAttribute("blah", true);
。当$this->authToken
路由被调用时null
最终成为_wdt
(因为它们没有用户上下文)。至少那是我的理论。
@Pavel是正确的,因为Symfony将两次请求之间的令牌设置为null,尽管我不认为这样做是security: false
。
使用令牌(if ($this->authToken) {...}
)之前检查令牌是否存在且不为null或为空(至少对我来说)。
@ utkarsh2k2,我确定您已经解决了问题……如果没有,您可以在致电$this->token_storage->getToken()
之前尝试检查->getUser()
中是否有东西。
答案 2 :(得分:0)
对我来说,解决方案是,当我给一个几乎干净的proyect做星时,仍然会遇到这个问题: “加载Web调试工具栏时发生错误。打开Web Profiler。
我的解决方案: 我在公共目录中添加了.htaccess
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^(.*)$ ./index.php/$1 [QSA,L]
RewriteCond %{HTTP:Authorization} ^(.*)
RewriteRule .* - [e=HTTP_AUTHORIZATION:%1]
只有工具栏出现。