2015-05-28 9 views
10

In meiner Symfony2-Anwendung habe ich einen Ausnahme-Listener erstellt, der mich über nicht behandelte Fehler informiert.Symfony: Ein Token wurde im SecurityContext für die Route hinter der Firewall nicht gefunden

Ich erhalte Meldungen über den folgenden Fehler, wenn Bots meine Seite besuchen, die sich hinter einer Firewall:

A Token was not found in the SecurityContext. 

ich abrufen auch die folgenden Daten:

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} 

Hier geht es um alles auf geschieht Meine Webseiten seit meinem letzten Update, aber ich kann nicht herausfinden, was das Problem ist. Wenn ich die Seite selbst besuche, gibt es kein Problem, keine Ausnahme wird ausgelöst.

Mein Verständnis der Firewall, die ich eingerichtet habe, war, dass, wenn jemand versucht, auf eine geschützte Ressource zuzugreifen, er auf die Anmeldeseite umgeleitet wird, ohne dass ein Fehler ausgelöst wird. Hier befürchte ich, dass einige Benutzer auf einer Fehlerseite landen, anstatt zur Anmeldeseite weitergeleitet zu werden. Und wenn ich den Fehler replizieren möchte, indem ich den Referer von dem Zeitpunkt an besuche, an dem der Fehler ausgelöst wird, werde ich korrekt umgeleitet, sodass ich nicht verstehe, in welchen Fällen der Fehler ausgelöst wird, im Gegensatz zu dem Benutzer, der umgeleitet wird.

EDIT:

Meine Ausnahme Listenerdienst:

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 } 

Meine Ausnahme Zuhörer Code:

<?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(
        '[email protected]', 
        '[email protected]', 
        ':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; 
    } 
} 

Meine Firewalls:

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 

Präzision:

  • Der E-Mail-Manager sendet nur eine E-Mail mit den angegebenen Parametern. es funktioniert gut
  • Der journalManager nur den Fehler protokolliert und hilft mir Fehler herauszufiltern bereits angemeldet
+0

Konnten Sie Code Ihres Ausnahmehörers zur Verfügung stellen? – kba

+0

Nun, der Ausnahme-Listener behandelt nur die Ausnahme, nein? hier möchte ich diese Ausnahme verhindern, die das Problem vorher löst. Ich könnte es noch posten, wenn Sie es nützlich finden, aber meine Vermutung wäre es würde eine Ablenkung werden –

+0

Es ist nicht offensichtlich, welche Art von Antwort Sie erwarten: die Ausnahme ** IS ** geworfen, wenn Sie versuchen, auf eine geschützte zuzugreifen Ressource ohne aktives Token. Wenn Sie nicht wollen, dass es erscheint - behandeln Sie es nicht. – zerkms

Antwort

4

Don nicht über diesen Fall/Fehler kümmern. Wenn Sie Ihren Fall selbst getestet haben, haben Sie das erwartete Verhalten (Weiterleitung zur Anmeldeseite) wie jeder andere "echte" Surfer.

Dann

User-Agent Mozilla/5.0 (compatible; AhrefsBot/5.0; + http://ahrefs.com/robot/)

Sie können sehen, dass die Seite von Ahrefs bot angefordert wird. Und wenn Sie eine Umleitung zu anderen Seiten als echte Surfer erhalten, verwendet es "Header" -Aktion. Aber Bots behandeln keine Header. Eigentlich ist es ein Fehler, den Amateur-Programmierer oft machen. Sie stellen so etwas wie

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

und dann funktioniert es für „echte“ Surfer, aber Bots können durch gehen und erreichen „angemeldet stuff“. In diesem Fall braucht es entweder den "Die" -Befehl direkt nach dem Header (in schlechtem Stil, der niemals Benutzer sein muss) oder den Ausnahmefehler (in gutem Stil).

Also Schlussfolgerung: Sie haben erwähnt, dass Sie kürzlich die Ausnahme erhalten haben, nachdem Sie den Code geändert haben, aber wahrscheinlich hat der Bot begonnen, etwas Neues zu crawlen, das vorher nicht gecrawlt wurde. Wahrscheinlich sollten Sie eine Regel hinzufügen, um diese Ausnahme zu überspringen, da sie nur auf Bots angewendet wird. Aber natürlich sollten Sie auch die letzten Änderungen überprüfen. Sie können auch das Protokoll einer solchen Ausnahme überprüfen und den Benutzer-Agent überprüfen, um sicherzustellen, dass er nur auf Bots angewendet wird.

+0

danke, ich dachte, es war mit dem Bot-Zeug verwandt. Ich habe den Zuhörer darauf eingestellt, Bots auszuschließen. Ich werde zurückkehren, um zu sagen, ob das die richtige Sache ist –

Verwandte Themen