views:

464

answers:

3

I'm using the CSRF hidden hash element with Zend_Form and trying to Unit Test the login but don't know how to write a Unit Test to include that element. Looked in the docs and read as many tutorials as I could find. I even delicioused them all, but no one mentions this.

+1  A: 

I set an environment variable in my Apache vhost file, which tells the code which server it's running on: development, staging, or production

The line for the vhost file is:

SetEnv SITE_ENV "dev"

Then I just make my forms react to the appropriate environment:

if($_SERVER['SITE_ENV']!='dev')
{
   $form_element->addValidator($csrf_validator);
}

I use this same technique for lots of stuff. For example, if it IS dev, I redirect all outgoing email to me, etc.

lo_fye
That's similar to what I ended up doing in the forms.ini file... I don't know why but not a fan of IF statements outside of scaffolding or .ini files for environment specific handling inside the main code. Just seems like a new environment would require looking in a ton of places to fix it up rather than .ini and bootstrap where you expect differences....
joedevon
+2  A: 

The correct hash is stored in the session, and the Hash form element has a Zend_Session_Namespace instance which contains the namespace for the hash.

To unit test the element, you would replace the Zend_Session_Namespace instance in the element (with setSession) with one you create yourself which contains the correct hash (the hash is stored in key "hash")

For further examples you could probably look at the Zend Framework unit tests for the Zend_Form_Element_Hash class. I would assume they have had to deal with this as well.

Jani Hartikainen
A: 

Csrf value is generated each time form is rendered. Hidden element of the form gets prefilled with that value. This value also gets stored in session. After submitting form, validation checks if value posted from the form is stored in session, if not then validation fails. It is essential, that form must be rendered during the test (so it can generate the hidden value and store it to session), then we can extract what is the hidden value out of rendered html, and later we can add hidden hash value into our request. Consider this example:

function testAddPageStoreValidData()
{
    // render the page with form 
    $this->dispatch('/form-page');

    // fetch content of the page 
    $html = $this->getResponse()->getBody();

    // parse page content, find the hash value prefilled to the hidden element
    $dom = new Zend_Dom_Query($html);
    $csrf = $dom->query('#csrf')->current()->getAttribute('value');

    // reset tester for one more request
    $this->resetRequest()
         ->resetResponse();

    // now include $csrf value parsed from form, to the next request
    $this->request->setMethod('POST')
                  ->setPost(array('title'=>'MyNewTitle',
                                  'body'=>'Body',
                                  'csrf'=>$csrf));
    $this->dispatch('/form-page');

    // ...
}
Lukas Normantas