Codestalker :: Dev Blog Symfony Framework, PHP, JavaScript, Bazy danych

20lip/102

Symfony 1.4 – Jak wyłączyć sprawdzanie csrf_token dla formy

W jednym z ostatnich projektów dopadła mnie konieczność wykonania pewnego tricku, który wielu wytrawnych programistów Symfony Framework oraz specjalistów od bezpieczeństwa może przyprawić o siwy włos :) . Problem: W jaki sposób mogę wyłączyć sprawdzanie csrf_token tylko dla jednej formy. Sytuacja tego typu wystąpiła podczas pisania modułu edycji użytkowników. Niestety nie mogłem skorzystać z przekazania obiektu do formy. Sytuacja wyglądała mniej więcej tak:
...
$myForm = new CustomForm();
$myForm->bind($myObj->parseToArray());
if($request->isMethod('post')){
$data = $request->getParameter($myForm->getName());
$myForm->bind($data);
if($myForm->isValid()){
... dalsza część kodu
}
}
...

Niestety pomimo szczerych chęci warunek if($myForm->isValid()) nigdy nie był VALID!!! Po wyświetleniu wszystkich błędów dowiedziałem się że przyczyna tkwi w polu _csrf_token które domyślnie było typu hidden. Jego zadaniem jest zabezpieczenie formy przed atakiem typu CSRF. Niestety w żaden sposób nie mogłem przekazać do tego pola poprawnej wartości. Skoro to mi się nie udało postanowiłem pójść w przeciwnym kierunku - postanowiłem pozbyć się problemowego pola :) . Jak to zrobić - dokumentacja Symfony podpowiedziała, że tworząc formę od razu można zdefiniować czy ma ona  zawierać zabezpieczenie przed CSRF. Odpowiada za to ostatni parametr konstruktora, któremu należy nadać wartość false.

Drobna modyfikacja kody wyglądała mniej więcej tak:

$myForm = new CustomForm(null, null, false);
Okazało się to strzałem w 10. Walidacja przechodziła bez problemu. Pozostaje jeszcze jeden problem - zabezpieczyć formę ponownie przed atakiem. Do tego celu wykorzystałem własne rozwiązanie oparte na generowaniu własnego tokena a następnie jego walidacji.

Jeżeli ktoś spotkał się z podobnym problemem i udało mu się to rozwiązać w inny sposób (bardziej elegancki) bardzo proszę o komentarz do artykułu.

Komentarze (2) Trackbacks (0)
  1. Hej,

    Bardziej elegancko wygląda metoda sfForm::disableLocalCSRFProtection() (http://www.symfony-project.org/api/1_4/sfForm#method_disablelocalcsrfprotection).
    Jak jej użyć? W akcji zrobić CustomForm::disableLocalCSRFProtection(), potem można przywrócić zmianę dzięki CustomForm::enableLocalCSRFProtection($secret) ($secret to chyba wartość wygenerowana w settings.yml, ale jak się do niej dobrać to Ci nie powiem, bo z głowy piszę).

    Druga opcja jest taka:
    $form = new CustomForm();
    unset($form['_csrf_token']);
    Daje właściwie ten sam efekt co Twoje rozwiązanie, ale tu się już raczej przywrócić ochrony nie da.

    Pozdrawiam.

  2. Hej,

    Serdeczne dzięki. Tego właśnie szukałem ale jak wiadomo potrzeba matką wynalazków;)

    Pozdrawiam


Dodaj komentarz


Brak trackbacków.