2010-04-05 7 views
7

Qualcuno può dirmi dove/come personalizzare il messaggio di errore del token CSRF per i moduli in Symfony 1.4. Sto usando sfDoctrineGuard per i login e in questo modulo in particolare, ogni volta che una sessione si esaurisce e la pagina è ancora aperta, genera un errore molto poco user-friendly: "Rilevato attacco CSRF". Qualcosa come "Questa sessione è scaduta. Torna alla home page e riprova" suona meglio.Symfony 1.4: messaggio di errore personalizzato per CSRF nei moduli

Qual è il modo giusto per farlo nella classe del modulo?

Grazie.

risposta

5

L'unico modo sembra essere quello di sovrascrivere sfForm::addCSRFProtection().

In /lib/form/BaseForm.class.php è possibile aggiungere questo pezzo di codice:

class BaseForm extends sfFormSymfony 
{ 
    public function addCSRFProtection($secret = null) 
    { 
     parent::addCSRFProtection($secret); 
     if (array_key_exists(self::$CSRFFieldName, $this->getValidatorSchema())) { 
      $this->getValidator(self::$CSRFFieldName)->setMessage('csrf_attack', 'This session has expired. Please return to the home page and try again.'); 
     } 
    } 
} 

Dopo la chiamata al metodo genitore, si recupera il validatore associato al campo CSRF e cambiare il messaggio per il codice csrf_attack.

Modifica: È inoltre necessario verificare se il validatore esiste o meno. Alcune forme potrebbero avere la loro protezione CSRF disabilitata!

Spero che questo aiuti!

+0

@naag: grazie mille. Ho provato un paio di cose, ma non quello, avrò un gioco. Sembra una piccola svista dai ragazzi di symfony. – Tom

+0

Ho modificato la mia risposta per includere un controllo dell'esistenza del validatore CSRF :-) – naag

2

In 1.4.4 ho dovuto modificare il codice di NAAG in questo modo ...

public function addCSRFProtection($secret = null) 
{ 
    parent::addCSRFProtection($secret); 
    if (isset($this->validatorSchema[self::$CSRFFieldName])) { 
    $this->validatorSchema[self::$CSRFFieldName]->setMessage('csrf_attack', 'This session has expired. Please refresh and try again.'); 
    } 
} 

Questa ottenuto lavorando, il 'token CSRF:' po 'appare ancora nel messaggio di errore però.

1

Suppongo che il prefisso "csrf token:" possa essere rimosso o personalizzato impostando l'etichetta del campo token CSRF, a livello globale ovviamente.

3

Nessuna di queste risposte spiega come rimuovere l'etichetta "Token CSRF:" che prefigura il messaggio di errore in un modo non hacker (ad esempio la modifica del nome del token è una cattiva idea!).

L'unico modo valido per rimuovere l'etichetta è estendere il validatore CSRF per generare un errore globale. Mentre lo facciamo, possiamo anche cambiare il messaggio di errore.

class myValidatorCSRFToken extends sfValidatorCSRFToken 
{ 
    protected function configure($options = array(), $messages = array()) 
    { 
    parent::configure($options, $messages); 
    $this->addMessage('csrf_attack', 'Your session has expired. Please return to the home page and try again.'); 
    } 

    protected function doClean($value) 
    { 
    try { 
     return parent::doClean($value); 
    } catch (sfValidatorError $e) { 
     throw new sfValidatorErrorSchema($this, array($e)); 
    } 
    } 
} 

Ora, cerchiamo di impostare i nostri moduli di usare questo validatore sovrascrivendo sfForm::addCSRFProtection in BaseForm:

public function addCSRFProtection($secret = null) 
{ 
    parent::addCSRFProtection($secret); 
    if (isset($this->validatorSchema[self::$CSRFFieldName])) //addCSRFProtection doesn't always add a validator 
    { 
    $this->validatorSchema[self::$CSRFFieldName] = new myValidatorCSRFToken(array(
     'token' => $this->validatorSchema[self::$CSRFFieldName]->getOption('token') 
    )); 
    } 
} 
2

Migliorare sulle risposte precedenti, ecco il codice che uso:

public function addCSRFProtection($secret = null) 
    { 
    parent::addCSRFProtection($secret); 
    if (isset($this->validatorSchema[self::$CSRFFieldName])) { 
     $this->validatorSchema[self::$CSRFFieldName]->setMessage('csrf_attack', 'This session has expired. Please refresh and try again.'); 
     $this->getWidgetSchema()->getFormFormatter()->setNamedErrorRowFormatInARow(" <li>%error%</li>\n"); 
    } 
    } 

Il Il valore predefinito per NamedErrorRowFormatInARow è "<li>%name%: %error%</li>\n" aggiungendo il nome e i due punti. Fai attenzione perché modifica il valore di tutti i moduli e tutti gli errori globali.

È inoltre possibile modificare il campo creando un formattatore di moduli personalizzato e utilizzandolo nei moduli desiderati.Puoi andare a guardare the documentation here per maggiori informazioni su questo.