I implemented support for Symfony's excellent CSRF protection in forms today. We had some forms we were rendering field by field, and so of course we had problems because we weren't calling $form->renderHiddenFields where we didn't think we had any. No problem, I've taken care of that, and I appreciate what a great feature this is to have "in the box" in Symfony.
But I still had problems with a few actions. These are cases where I need the user to supply some information on the first pass, such as uploading several images, and then provide more details on a second pass (you don't want to edit descriptions of images you aren't even looking at yet). My solution to this in the past has been to use two different form classes (often subclasses of the same parent), with different but compatible field sets. The first form takes a subset of the fields required for the second, so everything works. I use an extra "first_pass" parameter to clue in the second form that it shouldn't generate huffy validation errors, just quietly request all the as-yet-missing info. I suspect this is a fairly common pattern. Unfortunately I ran into a snag with CSRF. Turns out the CSRF token is built like this: md5($secret.session_id().get_class($this)); There are several pieces used here to arrive at the key that's hashed: The secret, unique to the application as a whole (usually) The user's PHP session ID The form class The third one is what bit me. I worked around it by removing .get_class($this) in my own override of this method in the form classes where I need to be able to submit data first to one form class and then to another. This leads to some questions: 1. Why include the form class in the key? The number of form classes in a particular application is relatively small. This only helps when form data for a currently live session has already been intercepted (which would mean you probably have the cookies too anyway) AND the form you're hoping to CSRF is a different form. That seems like a pretty narrow case, and it causes problems for legitimate applications like mine. 2. Just for curiosity: why have an application secret either? The PHP session ID is already unique, and you can't discover it unless you have the user's cookie for the Symfony-based site, which you won't if you're just dumping carefully crafted links and forms into an unrelated site to go phishing. I guess there's a small risk if you're using an incrementing MySQL ID as the session ID and it's very early in the lifetime of the site. The application secret certainly isn't hurting anything, I'm just curious about this part. -- Tom Boutell P'unk Avenue 215 755 1330 punkave.com window.punkave.com -- You received this message because you are subscribed to the Google Groups "symfony developers" group. To post to this group, send email to [email protected]. To unsubscribe from this group, send email to [email protected]. For more options, visit this group at http://groups.google.com/group/symfony-devs?hl=en.
