2011-10-13 8 views
6

Ho una situazione in cui è necessario eseguire codice se l'utente tenta di accedere a un URL protetto ed è non autenticato/autorizzato.È possibile vedere se un URL/percorso è protetto dietro il firewall programmaticamente?

Per impostazione predefinita, Symfony gestisce gli utenti non autenticati reindirizzando o inoltrando l'utente a un modulo di accesso. Mi piacerebbe evitare che ciò accada se il metodo di richiesta è POST, ed echeggiare invece un oggetto JSON.

Il modo migliore che posso pensare di gestire questa situazione è di creare un listener personalizzato che ascolta l'evento kernel.request e controlla due cose:

  • controlla se il metodo di richiesta è POST
  • controlla se il utente è completamente autenticati

Se è una richiesta POST, e l'utente non è pienamente autenticato, avrei eco un oggetto JSON.

Ma il mio ascoltatore è (prevedibilmente) attivo per tutte le richieste - Vorrei limitarlo per controllare solo se la richiesta è per un URL protetto dal firewall. È possibile controllare questo programma?

Ho anche un fastidioso sospetto c'è un modo più semplice per andare su questo, ma non si può capire, quindi se qualcuno ha qualche consiglio, mi piacerebbe sentire loro :)

Modifica
@Problematic - Il motivo per cui si controllano solo le richieste firewall è perché ho alcune richieste che non sono firewall, e se il mio codice viene attivato, riceverò l'oggetto JSON sopramenzionato invece della risposta reale della richiesta.

In questo momento se non si effettua l'accesso e si effettua una richiesta POST a api/get/something (che si trova dietro il firewall), Symfony restituisce l'HTML che descrive la pagina di accesso. Invece, voglio solo echo qualcosa come {error: 'User is not authorized'}. Ma voglio solo che questo accada per le richieste POST.

+0

Qual è il motivo per il solo controllo delle richieste firewall? – Problematic

+0

@Problematic, vedere la mia modifica –

risposta

3

Penso che stavo andando su questo nel modo sbagliato. Volevo sapere se c'era un URL dietro il firewall, ma penso che avrei dovuto cercare di scoprire se l'utente corrente era autorizzato per la richiesta. Essenzialmente, sapendo che a un utente è negato l'accesso a un URL significa che l'URL deve essere protetto da un firewall, altrimenti l'accesso non avrebbe potuto essere negato.

Tenendo presente questo, sono stato in grado di ottenere il risultato finale che volevo. E 'piuttosto semplice, una volta ci si rende conto come funziona il meccanismo di sicurezza ...

  • Symfony\Component\Security\Http\Firewall intercetta l'evento kernel.request
  • Firewall poi chiama un numero di ascoltatori di eventi che sono registrati in security.yml
  • Se una qualsiasi violazione della sicurezza (ovvero un utente che tenta di accedere a qualcosa senza essere connesso) viene rilevato, viene lanciato un numero AccessDeniedException e viene inviato l'evento kernel.exception.
  • Symfony/Component/Security/Http/Firewall/ExceptionListener ascolta l'evento e attiva il suo metodo onKernelException che decide qual è il passaggio successivo.Nel mio caso, sarebbe avviare il processo di autenticazione

Da quando ha cominciato il processo di autenticazione è quello che volevo evitare, ho scritto il mio listener di eventi che intercetta kernel.exception prima Symfony di ExceptionListener fa. Ho dato il mio listener di eventi una priorità di 1.

Questo è il metodo che ho scritto:

public function handleException(GetResponseForExceptionEvent $event) { 
     $exception = $event->getException(); 
     $request = $event->getRequest(); 
     if ($request->getMethod() == 'POST') { 
      if ($exception instanceof AccessDeniedException) { 
       $response = new Response({err: 'not logged in'}); 
       $event->setResponse($response); 
      } 
     } 
    } 

Fino a quando l'utente non è autorizzato, e il metodo di richiesta è POST, viene restituito un oggetto JSON (che interrompe anche la propagazione dell'evento) anziché il codice HTML per la pagina di accesso. In caso contrario, altri ascoltatori di kernel.exception reagiranno e Symfony potrà fare i suoi affari.

Quindi, la domanda originale rimane senza risposta, ma penso che potrebbe essere ottenuta controllando se un utente ha accesso a un'azione. Symfony\Component\Security\Core\Authorization\AccessDecisionManager sembra che sarebbe utile per questo.

Modifica
non so se questo metodo solo gestisce gli utenti che non sono connessi. Non ho ancora provato, ma penso che anche se un fuoco (loggato) l'utente tenta di accedere a un'azione che richiede un ruolo che non è stato concesso. Se questo causa un problema, proverei a modificarlo per utilizzare il metodo per preoccuparsi solo degli utenti che non hanno effettuato il login.

+0

Se si sta inviando una risposta JSON, è necessario aggiungere un controllo per verificare se si tratta di una richiesta Ajax che utilizza questo: $ request-> isXmlHttpRequest(). Questo è quello che ho usato per trasformare il metodo di autenticazione predefinito in un metodo Ajax. – HappyDeveloper

+0

@HappyDeveloper grazie per il suggerimento, ma sto ancora utilizzando un normale login di modulo. Avevo solo bisogno di reagire in modo diverso se veniva fatta una richiesta POST alle azioni protette e l'utente non era loggato. –

Problemi correlati