Best practice – Jak na spam z formulářů
- Ondřej Mirtes
- Člen | 1536
Ahoj,
již od úsvitu času používám ochranu formulářů proti spamu podle Jakuba Vrány a zatím mě nezklamala. Ve zkratce jde
o to, že k formuláři připojíte textové pole, do kterého má uživatel
vyplnit předem daný řetězec (který se ani nemusí měnit) a v duchu
progressive enhancement ho automaticky vyplníte a skryjete
javascriptem. Sází to na to, že boti javascript (a jQuery a načítání
skriptů z externích souborů) neumí, což možná jednou přestane platit,
ale zatím má tato metoda, co vím, 100% účinnost. A není otravná jako
Captcha.
Jak na to v Nette? Vytvoříme si potomka AppForm
pojmenovaného BaseForm
a toho budeme od této chvíle všude
používat. Abychom nezapomněli někde formulářovou ochranu přidat,
překryjeme metodu addSubmit
z FormContainer
, takže
k přidání dodatečného textového pole dojde při přidávání
potvrzovacího tlačítka.
Volitelně ještě můžete pomocí addProtection
přidat
ochranu proti CSRF a v celé aplikaci tak budete mít automaticky skutečně
neprůstřelné formuláře :)
Pro vyplnění a skrytí formuláře použijeme jQuery. Aby bylo řešení unobtrusive, přiřadíme labelu a controlu CSS třídu a navěšení javascriptu provedeme přes ní.
<?php
/* namespace Classes;
use Nette\Application\AppForm;
use Nette\Forms\Form; /**/
class BaseForm extends AppForm {
public function addSubmit($name, $caption) {
$this->addProtection('Form has expired.');
$noSpam = $this->addText('nospam', 'Fill in „nospam“')
->addRule(Form::FILLED, 'You are a spambot!')
->addRule(Form::EQUAL, 'You are a spambot!', 'nospam');
$noSpam->getLabelPrototype()->class('nospam');
$noSpam->getControlPrototype()->class('nospam');
return parent::addSubmit($name, $caption);
}
}
Následující javascript doporučuji mít v externím souboru spolu s ostatními skripty (zajaxování odkazů apod.):
$(function() {
$(".nospam").hide();
$("input.nospam").val("no" + "spam");
});
EDIT: 31.8.2009 – malý update. Při zavolání setDefaults
na Form
se zavolá isSubmitted()
a to zavolá
processHttpRequest()
, tudíž pak už nelze přidávat další
formulářová pole (do formuláře na vykreslení se přidají, ale
zpracovávající PHP skript je už nevidí). Nyní při použití
BaseForm
vyžaduji zavolat setDefaults
až po
přidání submitovacího tlačítka.
Párkrát jsem se spálil, kdy mi můj formulář hlásil útok spambota, přitom vše jsem měl v pořádku, až na to předčasné volání setDefaults.
EDIT: 14.9.2009 – po dnešním updatu formulářů již není kontrola volání setDefaults potřeba, vracím tedy kód třídy do původního stavu.
Editoval LastHunter (14. 9. 2009 19:12)
- ic
- Člen | 430
Taky mám něco podobného, akorát bez jQuery, formulář vykresluju
manuálně a pod ním je javascript a noscript (prostě jako v příkladu).
Není to tak elegantní, ale při pomalém načítání stránky neproblikává
mizající input.
- upravit
- Člen | 2
Supr, akorat bych dodal, ze je treba tento formular zpracovat metodou onSubmit. Nefunguje mi totiz:
<?php
$form->addSubmit('ok', 'Odeslat')->onClick[] = array($this, 'eventFormVzkazClick');
?>
ale tohlenc uz jo:
<?php
$form->onSubmit[] = array($this, 'handleFormSubmitted');
?>
- Ondřej Mirtes
- Člen | 1536
honzakuchar napsal(a):
Nešlo by to předělat do stylu
$form->addProtection();
?
Určitě, akorát místo addSubmit překryješ metodu addProtection. Já to ale chtěl mít všude a submitovací tlačítko mám taky všude, proto jsem to dal do něj.
- laada
- Člen | 35
LastHunter napsal(a):
honzakuchar napsal(a):
Nešlo by to předělat do stylu
$form->addProtection();
?
Určitě, akorát místo addSubmit překryješ metodu addProtection. Já to ale chtěl mít všude a submitovací tlačítko mám taky všude, proto jsem to dal do něj.
Hezke.
Mit to v metode addProtection() mi pripada kapku systemovejsi. Docela casto se taky pouziva odesilani formulare po udalosti onChange na selectboxu.
Editoval laada (16. 9. 2009 20:29)
- DocX
- Člen | 154
Pěkná práce.
Jen chci ale trochu komentnout to úvodní slovo
… Sází to na to, že boti javascript (a jQuery a načítání skriptů z externích souborů) neumí, což možná jednou přestane platit, ale zatím má tato metoda, co vím, 100% účinnost. A není otravná jako Captcha…
Na nějaké boty, slídící po netu a zkoušející automaticky odeslat jakýkoliv formulář to samozřejmě platí na 100%. Ale pokud si tvoji stránku vyčíhne nějaký zlotřilec a bude tě chtít zahltit spamem, vytvořit milion účtů, apod., tak to jistě dokáže jednoduše odpozorovat. Tam je captcha stále jediná možnost :)
- Ondřej Mirtes
- Člen | 1536
DocX napsal(a):
Pěkná práce.
Jen chci ale trochu komentnout to úvodní slovo
… Sází to na to, že boti javascript (a jQuery a načítání skriptů z externích souborů) neumí, což možná jednou přestane platit, ale zatím má tato metoda, co vím, 100% účinnost. A není otravná jako Captcha…
Na nějaké boty, slídící po netu a zkoušející automaticky odeslat jakýkoliv formulář to samozřejmě platí na 100%. Ale pokud si tvoji stránku vyčíhne nějaký zlotřilec a bude tě chtít zahltit spamem, vytvořit milion účtů, apod., tak to jistě dokáže jednoduše odpozorovat. Tam je captcha stále jediná možnost :)
Tak jasně, ale to už se dá řešit individuálně a třeba nějakým složitějším generováním, co se má zadat do toho pole, ale to jsem zatím nepotřeboval, nikdo to neprolomil :)