Произошла ошибка при загрузке веб-панели отладки

Я работаю над проектом Symfony 3.4 и столкнулся со странной проблемой. Панель инструментов веб-отладки не загружается и вместо этого выдает ошибку "Произошла ошибка при загрузке панели инструментов веб-отладки. Откройте веб-профилировщик". Вот скриншот

И когда я нажимаю на ссылку Открыть веб-профилировщик, я перехожу на другую страницу исключений. Вот его скриншот

Таким образом, после нескольких часов отладки я смог выяснить, что проблема находится в пользовательском слушателе. Он зарегистрирован в моем 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 }        

2 ответа

У меня была точно такая же проблема с использованием пользовательского прослушивателя с 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 устанавливает токен равным нулю между запросами, хотя я не думаю, что это security: false это делает это

Проверка того, что ваш токен существует и не является нулевым или пустым, прежде чем работать с ним (if ($this->authToken) {...}) исправляет проблему (по крайней мере для меня).

@ utkarsh2k2, я уверен, что вы уже исправили свою проблему... если нет, вы можете попробовать проверить это $this->token_storage->getToken() есть что-то перед звонком ->getUser(),

Я провел несколько экспериментов с вашим кодом и нашел это:

Удаление этих строк решает проблему:

    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 (dev firewall), поэтому я решил, что это не лучший способ.

Любые комментарии / дополнения приветствуются.

Решение для меня заключалось в том, что когда я запускал почти чистый проект, проблема все еще была: "Произошла ошибка при загрузке панели инструментов веб-отладки. Откройте веб-профилировщик".

Мое решение: я добавил.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]

При этом появляется только панель инструментов.

Другие вопросы по тегам