2010-02-20 3 views
9

Qual è il modo migliore per creare test funzionali per testare i moduli con la protezione CSRF abilitata in Symfony?Modulo di test funzionale con CSRF abilitato in Symfony

Attualmente ho aggiungere il seguente codice prima di ogni forma submittion:

$form = new sfGuardFormSignin(); 
    $token = $form->getCSRFToken(); 
    $token_name = $form->getCSRFFieldName(); 

Poi aggiungo il $ token e $ TOKEN_NAME per formare parametri come questo:

call('/login', 'POST', array (
    'signin' => 
    array (
     'username' => $username, 
     'password' => $password, 
     $token_name => $token, 
    ))) 

L'opzione suggerita nel la documentazione:

'_with_csrf' => true, 

Non funziona affatto.

C'è un modo più semplice per evitare di aggiungere token a ogni modulo testato manualmente? O c'è un modo per disattivare il controllo csrf durante l'esecuzione dei test?

Il modo in cui ho descritto sopra è ok quando devi testare 1-2 moduli ma se il progetto contiene decine di forme uniche diventa un dolore.

+0

T L'opzione di documentazione usa un'istanza di BaseForm da cui estendersi; il token CSRF viene generato utilizzando il tipo di modulo però, quindi MyFooForm! = BaseForm e quindi è per questo che l'opzione fallisce ... la tua opzione è il modo in cui ho finito di farlo anche nei miei progetti. – richsage

+0

C'è un altro motivo per cui fallisce pure. Aggiunge il token csrf all'elenco dei parametri, ma di solito nei moduli è negli array (come nell'esempio sopra). Quindi è completamente inutile :-(. Grazie per il tuo commento. – Stepashka

risposta

4

Ovviamente, non è possibile utilizzare l'opzione _with_csrf se si chiama direttamente l'url. È necessario passare dalla pagina del modulo, facendo clic sul pulsante di invio. Come così:

click('signin', array('signin' => array('username' => $username, 'password' => $password), array('_with_csrf' => true))) 

La stringa 'signin' devono essere adattati al form. Puoi anche usare una stringa più indipendente dall'etichetta, come "form # myform input [type =" submit "]" invece di "signin", adattando l'id del tuo modulo.

Come già suggerito, è possibile disattivare CSRF per l'accesso, è davvero utile per i moduli che modificano i dati.

3

Personalmente non uso test estensivi (probabilmente a mio danno), ma si può sempre disattivare la protezione CSRF nella classe del modulo per scopi di test.

public function configure() 

    $this->disableLocalCSRFProtection(); 
0

Spegnere CSRF per l'ambiente di test.

0

Si dovrebbe ottenere un token CSRF mostrando la pagina incluso il modulo.

$browser->get('/login'); 
$dom = new DOMDocument('1.0', $browser->getResponse()->getCharset()); 
$dom->loadHTML($browser->getResponse()->getContent()); 
$domCssSelector = new sfDomCssSelector($dom); 
$token = $domCssSelector->matchSingle('input[name="_csrf_token"]')->getNode()->getAttribute('value'); 
1

È possibile disattivare la protezione CSRF per tutte le forme solo con l'aggiunta ulteriore passaggio del compilatore:

class CsrfProtectionCompilerPass implements CompilerPassInterface 
{ 
    /** 
    * {@inheritdoc} 
    */ 
    public function process(ContainerBuilder $container) 
    { 
     $env = $container->getParameter('kernel.environment'); 
     if ($env == 'test') { 
      $container->setParameter('form.type_extension.csrf.enabled', false); 
     } 
    } 
} 

oppure è possibile disattivare completamente l'estensione form aggiungendo a config:

framework: 
    csrf_protection: false 

btw, le ultime soluzioni funzionano solo se non hai impostato in modo esplicito l'opzione modulo csrf_protection