Botvédelem kapcsolati űrlapra captcha nélkül
A saját oldalam kapcsolati űrlapját nem akartam captchával terhelni. Aki ajánlatot kér, ne kényszerüljön közlekedési lámpákat keresni a képeken. Ezért több, egymásra épülő láthatatlan réteget építettem, és külső szolgáltatást (Turnstile) csak akkor kapcsolok be, ha ezek kevésnek bizonyulnak.
Az öt réteg
- Csapdamező. Egy rejtett mezőt a botok kitöltenek, az emberek nem is látják.
- Időbélyeg. Az űrlap titkosított időbélyeget kap. Ha négy másodpercnél gyorsabban jön vissza, nem ember töltötte ki.
- Emberi jel. Egy mezőt a JavaScript tölt ki az első kattintás vagy billentyű után. Ha hiányzik, nem tiltok ki senkit, csak hosszabb időt várok el.
- Tartalom. Három hivatkozásnál több a levélben szinte mindig spam.
- Kliens. Az üres vagy robotos böngészőazonosítót nem engedem át.
public static function reason(Request $request): ?string
{
if ($request->filled('website')) { // honeypot: a hidden field only bots fill in
return 'honeypot';
}
$ua = strtolower((string) $request->userAgent());
if ($ua === '' || preg_match('/bot|crawl|spider|curl|wget|python|headless/', $ua)) {
return 'ua';
}
try {
$issued = (int) Crypt::decryptString((string) $request->input('_ts'));
} catch (\Throwable) {
return 'token';
}
$elapsed = time() - $issued;
if ($elapsed < 4) { // faster than a person can type
return 'too-fast';
}
// Set by JavaScript on the first real interaction. Without it, expect a slower visitor.
$humanSignal = preg_match('/^h[a-z0-9]{3,20}$/', (string) $request->input('_js')) === 1;
if (! $humanSignal && $elapsed < 20) {
return 'no-js';
}
if (preg_match_all('~https?://|www\.~i', (string) $request->input('message')) > 2) {
return 'links';
}
return null;
}
Kivonat valódi kódból, anonimizálva.
A bot ne tudja, hogy elbukott
Ha egy ellenőrzés elbukik, ugyanazt a sikeres képernyőt mutatom, mintha minden rendben lenne. A bot így semmilyen visszajelzést nem kap, amiből tanulhatna. Én közben a (személyes adat nélküli) naplóból látom, melyik réteg fogott meg valamit.
A valódi látogatóra is figyelni kell
A legfontosabb szabály az, hogy a védelem ne akadályozza a valódit. A JavaScript nélküli látogató sem marad ki, csak hosszabb időt várok el tőle, húsz másodpercet. Az űrlap egy napig érvényes, és ha lejár, a látogató kérést kap az újratöltésre, nem néma hibát.
Hasonló problémán dolgozol?
Ha elakadtál, vagy átnéztetnéd a megoldásodat, írj, szívesen megnézem.
Írok neked →További cikkek
Egy Laravel buktató: a throttle számláló közös
A throttle:5,1 és a throttle:120,1 ugyanazt a számlálót használja IP-nként. Így fogyasztotta el a mérés az űrlap korlátját.
Elolvasom →Szigorú CSP Laravelben, Vite-tal
Hogyan engedem a saját beágyazott szkriptjeimet egyedi azonosítóval, és tiltok le minden mást.
Elolvasom →