Sécuriser ses formulaires Zend_Form

La sécurité dans vos applications doit faire l’objet d’une attention particulière et permanente. Cet aspect dans la conception d’une solution et souvent négligé pour des raison de temps et d’économie.Il existe pourtant des solutions simples pour se protéger d’attaques comme les XSS ou, comme le montre la solution ci-dessous, des Spoofed Forms.

Cet exemple implémente une classe générique étendant Zend_Form et intégrant dynamiquement la génération et la vérification d’un token, certifiant ainsi que les données postées proviennent bien de votre formulaire :

class App_Form extends Zend_Form
{
    /**
     * @var Zend_Session_Namespace
     */
    protected $_session;

    public function __construct( $options = null )
    {
        parent::__construct( $options );
        $this -> _session = new Zend_Session_Namespace('default'); 

        // Automatically add a security token field
        $tokenField = new Zend_Form_Element_Hidden('__token');
        $this -> addElement($tokenField);
    }

    public function __toString()
    {
        // Generate a token for this form
        $token = md5(uniqid(''));
        $this -> getElement('__token') -> setValue( $token );
        $this -> _session -> { $this -> _tokenName() } = $token;

        return parent::__toString();
    }

    /**
     * Get the form token index in the session namespace
     *
     * @return string
     */
    private function _tokenName()
    {
        return strtolower(get_class($this)).'.token';
    }

    /**
     * Validate the form
     *
     * @param  array $data
     * @return boolean
     */
    public function isValid($data)
    {
        $valid = parent::isValid( $data );

        // Check the security token
        if( $this -> _session -> { $this -> _tokenName() } !== $data[ '__token' ])
        {
            $this -> addErrorMessage('Invalid token provided');
            $valid = false;

        }

        // Invalidate the generated token
        unset( $this -> _session -> { $this -> _tokenName() } );
        return $valid;
    }

}