AntispamControl – jednoduchý antispam
- nanuqcz
- Člen | 822
Ahoj,
implementoval jsem návrh pasivního antispamu od Jakuba Vrány pro Nette formuláře.
Použití
$form->addAntispam(); // to je vše :-)
Instalace
- Stáhněte soubor AntispamControl.php a uložte do
adresáře
libs
- V
BasePresenteru
registrujteAntispamControl
jako rozšíření formulářů
class BasePresenter
{
function startup()
{
AntispamControl::register();
}
}
Stránka s Addonem
Addon má svoji stránku zde.
Zatím jsem to nasadil na jeden web, kde chodil spam, a od té doby dobrý – asi měsíc bez jediného spamu. Pokud to ale nebude stačit a byl by zájem, přidám i další typy pasivních ochran (kontrola doby vyplňování formuláře apod.)
Editoval nanuqcz (18. 4. 2012 10:29)
- Tomáš Votruba
- Moderator | 1114
Mám bug při manuálním renderu:
{input antispam}
Pro fčnost musím upravit ř. 79
// z
document.getElementById('" . $control[0]->id . "').parentNode.parentNode.style.display = 'none';
// na
document.getElementById('" . $control[0]->id . "').style.display = 'none';
aby se mi neschovával celý formulář.
- uestla
- Backer | 799
Osobně se mi tahle „přehnaná“ lenost moc nelíbí/nehodí. Jako pomocníka bych to vnímal, přidalo-li by mi to antispamový prvek a nastavilo hodnotu, kterou to má/nemá mít.
Kdybych si formulář vykreslil hodně po svém, už mi bude generovaný javascript dělat neplechu. Mohl bych si ho ručně upravit, ale pak už není komponenta použitelná plošně, ale jen pro daný případ.
Vytvářet děděné komponenty pro každý zvláštní případ také není moudré.
Osobně si skrývání prvků při zapnutém javascriptu realizuji pomocí triku z legendárního komentáře u Jakuba Vrány:
<style>.js .hidden { display: none; }</style>
<body>
<script type="text/javascript">document.body.className += ' js';</script>
{form ...}
{input antispam, class => 'hidden'}
{/form}
Myšlenka je každopádně dobrá, můj výstup je zde.
Editoval uestla (6. 5. 2012 16:11)
- nanuqcz
- Člen | 822
uestla: Taky hezké. Jen jsem nenašel, kde se v tvojem
výstupu nastavuje class="hidden"
pro formulář renderovaný
klasicky (přes DefaultFormRenderer).
Každopádně přehnaná lenost mě osobně vyhoduje. V tvojem řešení musím kromě „instalace“ AntispamControlu ještě přidat jeden řádek do CSS a jeden řádek javascriptů :-) Ale tohle je věc názoru (jednoduchost vs. komplexnost)
- uestla
- Backer | 799
Tak samozřejmě, každý svého štěstí strůjcem. Původně jsem tam přidání třídy napevno měl, ale vykresluji-li ručně do tabulky, bylo by zbytečné mít ve výsledku něco jako
<tr class="hidden"> <!-- přidané mnou -->
<td><input ... class="hidden"></td> <!-- způsobené na straně serveru -->
</tr>
Proto nevidím problém – chci-li vykreslit DefaultRenderer
em
a vím o tom – ve využití vrácené hodnoty:
$antispam = $form->addAntispam();
$antispam->controlPrototype->class('hidden');
$antispam->labelPrototype->class('hidden');
Osobně ale daleko častěji vykresluji pomocí
{form ...}
maker.
O generovaném javascriptu asi ani nemluvě :-( Ale proti gustu žádný dišputát (abychom nezůstali pouze u jednoho moudrosloví ;-)).
Editoval uestla (6. 5. 2012 20:34)
- Tomáš Votruba
- Moderator | 1114
Tak jsem nasadil do twitter-modal (možná to má nějakou relevanci) a chodí mi mnohem více spamů. Mohl bych poprosit ještě o nějaké zmiňované ochrany? Případně doporučení, díky
- nanuqcz
- Člen | 822
Schumtzka: Ještě více spamů než předtím? :-) To je zvláštní. Za 3 týdny končím školu a státnicuju, tak nevím, jestli se k tomu teď dostanu. Pokud by se ti ale chtělo, můžeš tam zkusit implementovat třetí bod z tohohle článku, pokud se k tomu nedostanu dřív.
- MartinitCZ
- Člen | 580
Mnohem jednodušší řešení mi přijde přidat input „email“, který bude skryt pro uživatele, ale bot ho vyplní.
A po odeslání jen kontrolovat, jestli je prázdný ⇒ pokračovat, něco obsahuje ⇒ redirect doPryč.
Ale nikdy jsem nezkoumal úspešnost určitých řešení proti spamu ;)
- nanuqcz
- Člen | 822
martinit: Ale vždyť přesně takhle ten addon funguje :-)
Akorát se pole nejmenuje email
. Ale pokud chceš, aby se tak
jmenovalo, jde to jednoduše nastavit:
$form->addAntispam('email');
EDIT: Možná tě zmátlo, že se kontroluje doba odeslání příspěvku. To je jen kontrola „navíc“ ke způsobu, který jsi popsal ty ;-)
Editoval nanuqcz (10. 5. 2012 15:14)
- ic
- Člen | 430
Nevadí tohle nástrojům na automatické vyplňování formulářů ( http://www.zive.cz/…default.aspx )? Myslím, že takový nástroj by antispamem neprošel.
- Tomáš Votruba
- Moderator | 1114
@ic: Nerozumím, co tím tohle myslíš. Pokud náhodou reaguješ na čas, tak na login form se antispam nehodí (kde se hodí automatické vyplňování), ale všude jinde uživatel aspoň něco napsat musí (heslo, adresu…).
Také by se hodilo vědět, jak dlouho to trvá robotům :).
@nanuqcz: Díky, čas funguje!
- nanuqcz
- Člen | 822
Také by se hodilo vědět, jak dlouho to trvá robotům :).
Až bude čas, přemýšlel jsem, že si udělám nějaké statistiky :-) Ale
jestli tě to moc zajímá, tak si přidej do addRule
nějaké
logovací funkce.
$form->addHidden('form_created', time())
->addRule(
function($item){
$value = (int)$item->value;
//------log
if ($value <= (time() - AntispamControl::$minDelay)) {
file_put_contents('antispam.log', 'Fill time: ' + (time() - AntispamControl::$minDelay) + ' s \n', FILE_APPEND);
}
//------/
return $value <= (time() - AntispamControl::$minDelay);
},
$msg
);
Editoval nanuqcz (10. 5. 2012 19:40)
- Bazylek
- Člen | 22
Ahojte,
prosím o radu, při implementaci došlo k chybě :
Argument 1 passed to Nette\Forms\AntispamControl::addAntispamScript() must be an instance of Nette\Utils\Html, instance of Nette\Web\Html given, called in C:\website\inlinesports\libs\AntispamControl.php on line 82 and defined
nemůžu přijít na to, kde dělám chybu.
HomepagePresenter
public function createComponentKontaktForm()
{
$form = new AppForm($this, 'kontaktForm');
$model = new \UsersModel();
$uzivemail = $this->getParam('id');
$defaults = $model->getUser($uzivemail);
$userExists = $defaults && !empty($defaults);
$form->addText('jmeno', 'Vaše jméno', 35)
->addRule($form::FILLED, 'Vypňte Vaše jméno');
$form->addText('email', 'Váš e-mail', 35)
->addRule($form::FILLED, 'Vyplňte svůj email')
->addRule($form::EMAIL, 'Vyplňte platný email');
$form->addTextArea('zprava', 'Text emailové zprávy', 40, 200);
$form->addSubmit('save', 'Odeslat')
->onClick[] = callback($this, 'emailOdesli');
$form->renderer->wrappers['controls']['container'] = 'dl';
$form->renderer->wrappers['pair']['container'] = NULL;
$form->renderer->wrappers['label']['container'] = 'dt';
$form->renderer->wrappers['control']['container'] = 'dt';
$form->addAntispam();
return $form;
}
Děkuji za každou radu
- Bazylek
- Člen | 22
To jsem zkoušel,
use Nette\Forms\Controls\TextInput,
Nette\Forms\Form,
Nette\Utils\Html,
Nette\Web\Html;
ale hazeí mi to
Cannot use Nette\Web\Html as Html because the name is already in use
Pokud bych přešel na novou verzi, tak bych musel předělat celý web. Bylo by
to moc pracné.
Děkuji za radu, špatně jsem přečtl tvou odpověď.
s tímto to funguje
use Nette\Forms\Controls\TextInput,
Nette\Forms\Form,
Nette\Web\Html;
Editoval Bazylek (4. 6. 2012 13:46)
- Jesper
- Člen | 4
Zdravím, nevím jestli něco dělám zle či ne, ale nette mne vždy zdupe. Verze 2.0.10
Nette\InvalidStateException
Method BasePresenter::startup() or its descendant doesn't call parent::startup().
Jsem začátečník s Nette a postupoval jsem přesně podle návodu. Díky za rady .. třeba je fakt chyba jen na mé straně.
- jolan
- Člen | 5
Navrhuji doplnit jěště podmínku
$this->addRule(Form::EQUAL, $msg, '');
Pokud to totiž chápu správně, tak ~Form::FILLED projde i v případě, kdy položka nebyla v POST-u vůbec zaslána. To se ale často stáva, protože roboti (z mých zkušeností) stahují HTML kód formuláře pouze jednou a následně na něj už sypou POST-ové požadavky podle položek, které Form měl při první návštěve. Když tam ale správce webu doplní antispamovou ochranu až poté, co zjistí, že mu chodí moc spamu, robot toto pole už v POST-ových požadavcích nedoplní, tudíž je podmínka pokaždé true.
Filip Procházka napsal(a):
$this->addRule(~Form::FILLED);
Editoval jolan (6. 1. 2014 16:55)
- MartinitCZ
- Člen | 580
Addon je zbytečnost. Stačí přidat do továrničky formuláře:
$this->addHidden('email');
nebo
$this->addHidden('mail')
Roboti toto rádi vyplní, jelikož je to „email“ pole :)
Ve zpracování formuláře použiješ:
if ($values->email) { // Pokud je toto vyplněno, tak to nejspíš bude robot (případně nějaký štoura :D)
$this->redirect('Homepage:default');
}