Nette podporuje CSRF ochranu formulářů, prostřednictvím skrytého formulářového pole, do kterého se uloží CSRF token, jenž se s vygenerováním zapamatuje v session a po odeslání se token, uložený v session, ověřuje vůči odeslanému tokenu.
Pokud jste někdo něco podobného nasadili, pravděpodobně jste se již setkali s problémem, kdy vykreslení formuláře způsobí varování “HTTP headers already sent”. Zkrátka, že se pokoušíte (v tomto případě) startovat session až v okamžiku, kdy již HTTP hlavičky byly odeslány a není možné již poslat další. To se typicky děje, pokud máte nakonfigurovanou Nette session v režimu autoStart: smart - tedy “vytvoř session až v okamžiku, kdy je potřeba”. Za předpokladu, že využíváte výchozí souborové úložiště pro session ID na straně server, je toto chování výhodné v tom, že se nevytváří nové session soubory s každým přístupem nového uživatele, avšak vytvoří se, až když je potřeba skutečně do session něco zapsat. To však může být právě v kombinaci s CSRF ochranou formulářů problém. Nastartování session totiž způsobuje zapsání session ID do cookie (pokud ještě nebylo vygenerováno), které se přenáší právě skrz HTTP hlavičky. Jenže ty již mohly být v onen okamžik odeslány a problém je na světě.
Nejjednodušším řešením je přepnout Nette session do režimu autoStart: true, tedy aby se starovala automaticky. Díky tomu bude session ID cookie již nastavena a nestane se vám, že by se ji Nette pokoušelo vytvářet až na žádost, např. v okamžiku vykreslování stránky, kdy už jsou HTTP hlavičky poslány.
Druhou možností je před samotným vykreslením (typicky ještě před zpracováním signálu někde ve startup/action* metodě) inicializovat formulář tak, aby se vždy před vytvořením kompletně sestavil, a tím pádem se natartovala session před započetím vykreslování HTML stránky.
Automatické startování session má však i své nevýhody:
V Netwings 7 máme tuto ochranu zapnutou by-default na produkčním prostřední nad všemi formuláři. Pokud vývojář chce, může ji vypnout (nad konkrétním formulářem nebo i globálně). Navíc máme upravený způsob vykreslení formulářového prvku CsrfProtection takovým způsobem, že se samotný HTML input s tokenem vykresluje pouze jako data-atribut jiného (div) elementu a poté až Javascript způsobí jeho vložení do formuláře.
Tím vynucujeme mít povolený a aktivní Javascript. V dnešní době se bez Javascriptu na webu beztak neobejdete, čili pro běžného uživatele to není nijak limitující a alespoň tím určitým způsobem odstřihnete případné “hloupé” roboty (ve smyslu neumějící Javascript) nabízející viagry a podobné srandy za úžasné ceny.