Php Symfony:在SecurityContext中未找到防火墙后路由的令牌

Php Symfony:在SecurityContext中未找到防火墙后路由的令牌,php,symfony,error-handling,bots,Php,Symfony,Error Handling,Bots,在我的Symfony2应用程序中,我构建了一个异常侦听器,让我知道未处理的错误 当机器人程序访问位于防火墙后面的我的页面时,我收到有关以下错误的消息: A Token was not found in the SecurityContext. 我还检索了以下数据: User agent Mozilla/5.0 (compatible; AhrefsBot/5.0; +http://ahrefs.com/robot/) Trace as string #0 /home/foodmeup.net

在我的Symfony2应用程序中,我构建了一个异常侦听器,让我知道未处理的错误

当机器人程序访问位于防火墙后面的我的页面时,我收到有关以下错误的消息:

A Token was not found in the SecurityContext.
我还检索了以下数据:

User agent  Mozilla/5.0 (compatible; AhrefsBot/5.0; +http://ahrefs.com/robot/)
Trace as string #0 /home/foodmeup.net/production/releases/20150527141710/app/cache/prod/classes.php(2951): Symfony\Component\Security\Http\Firewall\AccessListener->handle(Object(Symfony\Component\HttpKernel\Event\GetResponseEvent))
#1 [internal function]: Symfony\Component\Security\Http\Firewall->onKernelRequest(Object(Symfony\Component\HttpKernel\Event\GetResponseEvent), 'kernel.request', Object(Symfony\Component\EventDispatcher\ContainerAwareEventDispatcher))
#2 /home/foodmeup.net/production/releases/20150527141710/app/cache/prod/classes.php(2205): call_user_func(Array, Object(Symfony\Component\HttpKernel\Event\GetResponseEvent), 'kernel.request', Object(Symfony\Component\EventDispatcher\ContainerAwareEventDispatcher))
#3 /home/foodmeup.net/production/releases/20150527141710/app/cache/prod/classes.php(2138): Symfony\Component\EventDispatcher\EventDispatcher->doDispatch(Array, 'kernel.request', Object(Symfony\Component\HttpKernel\Event\GetResponseEvent))
#4 /home/foodmeup.net/production/releases/20150527141710/app/cache/prod/classes.php(2299): Symfony\Component\EventDispatcher\EventDispatcher->dispatch('kernel.request', Object(Symfony\Component\HttpKernel\Event\GetResponseEvent))
#5 /home/foodmeup.net/production/releases/20150527141710/app/bootstrap.php.cache(3017): Symfony\Component\EventDispatcher\ContainerAwareEventDispatcher->dispatch('kernel.request', Object(Symfony\Component\HttpKernel\Event\GetResponseEvent))
#6 /home/foodmeup.net/production/releases/20150527141710/app/bootstrap.php.cache(2990): Symfony\Component\HttpKernel\HttpKernel->handleRaw(Object(Symfony\Component\HttpFoundation\Request), 1)
#7 /home/foodmeup.net/production/releases/20150527141710/app/bootstrap.php.cache(3139): Symfony\Component\HttpKernel\HttpKernel->handle(Object(Symfony\Component\HttpFoundation\Request), 1, true)
#8 /home/foodmeup.net/production/releases/20150527141710/app/bootstrap.php.cache(2383): Symfony\Component\HttpKernel\DependencyInjection\ContainerAwareHttpKernel->handle(Object(Symfony\Component\HttpFoundation\Request), 1, true)
#9 /home/foodmeup.net/production/releases/20150527141710/web/app.php(28): Symfony\Component\HttpKernel\Kernel->handle(Object(Symfony\Component\HttpFoundation\Request))
#10 {main}
自从上次更新以来,我所有的网页上都出现了这种情况,但我不知道问题出在哪里。 如果我亲自访问该页面,则不会出现任何问题,也不会引发任何异常

我对我设置的防火墙的理解是,如果有人试图访问受保护的资源,他将被重定向到登录页面,而不会抛出任何错误。在这里,我担心一些用户可能会登录到错误页面,而不是被重定向到登录页面。当我想通过在抛出错误时访问referer来复制错误时,我被正确地重定向了,所以我不知道抛出错误与重定向用户的情况是什么

编辑:

我的异常侦听器服务:

exception_listener:
    class: %exception_listener.class%
    arguments: [@router, @session, @security.token_storage, @email_manager, @doctrine, "@=service('kernel').getEnvironment()", @security.authorization_checker]
    tags:
        - { name: kernel.event_listener, event: kernel.exception, method: onKernelException, priority: 250 }
我的异常侦听器代码:

<?php

namespace AppBundle\EventListener;

use AppBundle\Application\Core\EmailManager;
use AppBundle\Application\Core\JournalManager;
use AppBundle\Entity\User\User;
use AppBundle\Security\Voter\SubscriptionVoter;
use Doctrine\Bundle\DoctrineBundle\Registry;
use Symfony\Bundle\FrameworkBundle\Routing\Router;
use Symfony\Component\HttpFoundation\RedirectResponse;
use Symfony\Component\HttpFoundation\Request;
use Symfony\Component\HttpFoundation\Session\Session;
use Symfony\Component\HttpKernel\Event\GetResponseForExceptionEvent;
use Symfony\Component\Security\Core\Authentication\Token\Storage\TokenStorage;
use Symfony\Component\Security\Core\Authorization\AuthorizationChecker;


class ExceptionListener
{
    /**
     * @var Router
     */
    private $router;

    /**
     * @var Session
     */
    private $session;

    /**
     * @var TokenStorage
     */
    private $tokenStorage;

    /**
     * @var EmailManager
     */
    private $emailManager;

    /**
     * @var null
     */
    private $environment;

    /**
     * @var AuthorizationChecker
     */
    private $authorizationChecker;
    /**
     * @var Registry
     */
    private $doctrine;

    public function __construct(Router $router, Session $session, TokenStorage $tokenStorage, EmailManager $emailManager, Registry $doctrine ,$environment=null, AuthorizationChecker $authorizationChecker)
    {
        $this->router = $router;
        $this->session = $session;
        $this->tokenStorage = $tokenStorage;
        $this->emailManager = $emailManager;
        $this->environment = $environment;
        $this->authorizationChecker = $authorizationChecker;
        $this->doctrine = $doctrine;
    }

    public function onKernelException(GetResponseForExceptionEvent $event)
    {
        try {
            /** @var $exception */
            $exception = $event->getException();
            $request = $event->getRequest();
            $referer = $request->headers->get('referer');

            $manager = $this->doctrine->getManager('logging');
            $journalManager = new JournalManager($manager);

            if($exception->getCode() == 403)
            {
                if ($this->authorizationChecker->isGranted(SubscriptionVoter::HAS_SUBSCRIPTION) && !$this->authorizationChecker->isGranted(SubscriptionVoter::SUBSCRIPTION_VALID))
                {
                    $this->session->getFlashBag()->add('warning',"La page précédente n'est pas accessible avec ce portfolio car le paiement n'est pas à jour. Vous devez actualiser votre paiement.");
                    $response = new RedirectResponse($this->router->generate('renew_subscription'));
                }
                else
                {
                    $this->session->getFlashBag()->add('warning',"La page précédente n'est pas accessible avec vos droits d'accès et vous avez été redirigé vers l'accueil du site.");
                    $response = new RedirectResponse($this->router->generate('home'));
                }

                $event->setResponse($response);
            }
            elseif ($exception->getMessage() == "Couldn't connect to host, Elasticsearch down?" || $exception->getCode() == 52)
            {
                $this->session->getFlashBag()->add('warning', "La service de recherche du site a arrêté de fonctionner. Renouvellez votre dernière action si celle si n'a pas été suivie d'effet d'ici 2 minutes.");
                $event->setResponse(new RedirectResponse($request->headers->get('referer') ?: $this->router->generate('home')));
            }
            elseif (
                !($exception->getCode() == 404 && !$referer) &&
                !($this->contains($exception->getMessage(), array('object not found', 'A Token was not found in the SecurityContext', 'No route found for')) && !strpos($referer, 'foodmeup')) &&
                !in_array($this->environment, array('dev', 'test')) &&
                !$journalManager->errorExists($exception, $request->getUri(), 1)
            )
            {
                $user = is_object($this->tokenStorage->getToken()) ? $this->tokenStorage->getToken()->getUser() : null;
                $user = $user instanceOf User ? $user : null;
                $code = $exception->getCode();

                $this->emailManager->sendEmail(
                    'error@foodmeup.net',
                    'foodmeup@foodmeup.net',
                    ':Core/Email:error.html.twig',
                    "Une erreur $code s'est produite sur le site",
                    array(
                        'date' => new \DateTime(),
                        'user' => $user,
                        'exception' => $exception,
                        'referer' => $request->headers->get('referer'),
                        'current' => $request->getUri(),
                        'user_agent' => $_SERVER['HTTP_USER_AGENT']
                    )
                );

                $journalManager->addErrorLog($exception, $request->getUri());
            }
        } catch (\Exception $e)
        {
        }

    }

    private function contains($str, array $arr)
    {
        foreach($arr as $a) {
            if (stripos($str,$a) !== false) return true;
        }
        return false;
    }
}
精度:

  • emailManager只发送一封包含给定参数的电子邮件。 它很好用
  • journalManager只是记录错误并帮助我 筛选出已记录的错误

    • 不要担心这种情况/错误。当你们自己测试你们的情况时,你们得到了预期的行为(重定向到登录页面)和任何其他“真正的”冲浪者一样

      然后

      用户代理Mozilla/5.0(兼容;AhrefsBot/5.0; +)

      您可以看到该页面是由Ahrefs bot请求的。当你作为真正的冲浪者重定向到其他页面时,它会使用“标题”动作。但是机器人不处理标题。所以实际上这是业余程序员经常犯的错误。他们放了一些类似的东西

      if($notallowed){
       header('Location: /login');
      }
      //... only logged stuff ...// 
      
      然后它适用于“真正的”冲浪者,但机器人可以通过并接触“记录的东西”。所以,在这种情况下,它要么需要在头之后立即使用“die”命令(使用糟糕的样式,决不能是user),要么抛出异常(使用良好的样式)


      所以结论:您提到,您最近在更改代码后遇到了异常,但最有可能的是,bot开始爬网以前没有爬网过的新内容。因此,您很可能应该添加一条规则来跳过该异常,因为它仅适用于机器人程序。当然,你也应该回顾一下最近的变化。您还可以查看此类异常的日志并检查用户代理,以确保它仅应用于机器人。

      您可以提供异常侦听器的代码吗?嗯,异常侦听器只处理异常,不是吗?在这里,我想防止这个异常,这是解决之前的问题。如果您觉得它有用,我仍然可以发布它,但我猜它会让您分心。您希望得到什么样的答案并不明显:当您尝试在没有活动令牌的情况下访问受保护的资源时,会引发异常。如果你不想让它出现,就不要处理它。好吧,我对我设置的防火墙的理解是,如果有人试图访问受保护的资源,他会被重定向到登录页面,而不会抛出任何错误。在这里,我担心一些用户可能会登录到错误页面,而不是被重定向到登录页面。当我想通过访问页面进行复制时,我被正确地重定向了,所以我不知道抛出错误与重定向用户的情况是什么。谢谢,我认为这与bot相关。我已经让侦听器排除了机器人,我将再次告诉您是否应该这样做
      if($notallowed){
       header('Location: /login');
      }
      //... only logged stuff ...//