簡體   English   中英

Symfony:SecurityContext中沒有為防火牆后面的路由找到令牌

[英]Symfony: A Token was not found in the SecurityContext for route behind firewall

在我的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;
    }
}

我的防火牆:

firewalls:
    dev:
        pattern:  ^/(_(profiler|wdt)|css|images|js)/
        security: false
    guest:
        pattern:        /(public/|$|genemu-captcha-refresh|media/cache/)
        anonymous:      true
        context:        main_auth
    main:
        pattern:        ^/
        anonymous:      false
        provider:       main
        context:        main_auth
        switch_user: { role: ROLE_ADMIN, parameter: _switch_user_parameter }
        form_login:
            login_path: fos_user_security_login
            check_path: fos_user_security_check
            success_handler: authentication_site_handler
        logout:
            path:       fos_user_security_logout
            target:     /
        remember_me:
            key:      "%secret%"
            lifetime: 86400 #en secondes
            path:     /
            domain:   ~ # Prend la valeur par défaut du domaine courant depuis $_SERVER
        oauth:
            remember_me: true
            resource_owners:
                facebook:           "/loginhwi/check-facebook"
                github:             "/loginhwi/check-github"
                google:             "/loginhwi/check-google"
                twitter:            "/loginhwi/check-twitter"
                linkedin:           "/loginhwi/check-linkedin"
                flickr:             "/loginhwi/check-flickr"
            login_path:        fos_user_security_login
            check_path:        fos_user_security_check
            failure_path:      fos_user_security_login
            success_handler:  authentication_site_handler
            oauth_user_provider:
                service: fosubuser.provider

精度:

  • emailManager只發送一封來自給定參數的電子郵件。 它工作正常
  • journalManager只記錄錯誤並幫助我過濾掉已記錄的錯誤

不要擔心這種情況/錯誤。 當你自己測試你的情況時,你得到的預期行為(重定向到登錄頁面)就像任何其他“真正的”沖浪者一樣。

然后

用戶代理Mozilla / 5.0(兼容; AhrefsBot / 5.0; + http://ahrefs.com/robot/

您可以看到該頁面是由Ahrefs bot請求的。 當你作為真正的沖浪者重定向到其他頁面時,它使用“標題”動作。 但機器人不處理標題。 所以實際上這是業余程序員經常犯的錯誤。 他們提出類似的東西

if($notallowed){
 header('Location: /login');
}
//... only logged stuff ...// 

然后它適用於“真正的”沖浪者,但機器人可以通過並達到“記錄的東西”。 所以在這種情況下,它要么在標題之后需要“die”命令(在壞樣式中必須永遠不是用戶)或拋出異常(以良好的方式)。

所以結論:你提到你最近在更改代碼后得到了異常,但很可能機器人開始抓取以前沒有抓過的新內容。 所以很可能你應該添加一個規則來跳過該異常,因為它只適用於機器人。 但是你當然也應該檢查你最近的變化。 您還可以查看此類異常的日志並檢查用戶代理以確保它僅應用於機器人。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM