Fiecare protecție de mai jos se pornește, se oprește și se reglează din dashboard, pe cheia ta API. Aici scrie ce face fiecare și când merită s-o folosești; unde și cum le montezi în cod e la sfârșitul paginii.
Detectare boți
Blochează clienții automatizați — scripturi, scrapere, boți — recunoscându-i după cum se prezintă.
În dashboard alegi ce crawlere lași să treacă — de obicei Google și Bing, pe care le vrei pe site pentru indexare.
Validare email
Verifică adresa de email din cerere și respinge ce nu e bun.
Două comutatoare în dashboard:
- Blochează adresele temporare — cele „de unică folosință", pe care cineva le ia ca să treacă de confirmarea pe email. Pornit implicit.
- Blochează providerii gratuiți — gmail, yahoo și restul. Oprit implicit, și așa ar trebui să rămână pentru majoritatea produselor: altfel respingi jumătate din clienții reali.
Pe lângă ele, poți ține două liste proprii: domenii pe care le refuzi în plus față de lista noastră, și domenii pe care le accepți întotdeauna (util pentru un client mare al cărui domeniu ar nimeri din greșeală într-o listă publică).
Ce prinde:
| Motiv | Când |
|---|---|
| adresă temporară | domeniu de mail de unică folosință (peste 450 cunoscute) |
| sintaxă invalidă | nu arată a email |
| prea lungă | depășește limita standard de lungime |
| provider gratuit | doar dacă pornești blockFree |
De asemenea, îți dă înapoi forma canonică a adresei — utilă ca să nu lași aceeași persoană
să-și facă mai multe conturi cu variații de puncte sau +alias la gmail. Detalii în
Protecția înregistrării.
Verificare de domeniu
Verifică în DNS dacă domeniul din adresă chiar există. Un domeniu inventat acum zece minute nu apare pe nicio listă de domenii temporare, dar DNS-ul spune adevărul: dacă domeniul nu există, adresa nu poate primi niciodată un email de confirmare.
Din dashboard poți escalada și cazul „domeniul există, dar nu are server de mail configurat". E oprit implicit, fiindcă există configurări neobișnuite dar valide care ar fi respinse pe nedrept; îl vezi oricum în loguri, marcat ca neblocat.
Verdictele se țin în memorie la noi (șapte zile cele pozitive, șase ore cele negative), deci verificarea aproape niciodată nu adaugă timp cererii tale.
Limită per adresă
Limitează câte încercări poate face aceeași adresă de email, indiferent cum e scrisă.
E protecția care prinde ce nu prinde nicio alta: cineva care își face conturi cu
ion.popescu+1@gmail.com, ion.popescu+2@gmail.com, i.o.n.popescu@gmail.com — pentru gmail
toate sunt aceeași cutie poștală, iar noi le numărăm la fel. Din dashboard alegi câte încercări
permiți și pe ce interval.
Validare nume
Prinde numele generate aleator, tipice conturilor false (fveZAcUnQKxdOjIpCjX), fără să
respingă nume reale — inclusiv nume scurte sau scrise cu alfabete non-latine.
Din dashboard reglezi lungimea minimă și maximă acceptată.
Blocare atacuri (shield)
Oprește tiparele de atac clasice — SQL injection, XSS, path traversal — în adresa cererii, în parametri și în conținut.
Pornită implicit. Din dashboard alegi dacă se scanează și conținutul cererii (pornit implicit).
Date sensibile
Detectează numere de card (validate corect, nu orice 16 cifre), emailuri sau telefoane în conținutul cererii.
Oprită implicit: ce anume e „sensibil" depinde de ce colectezi tu. Din dashboard bifezi tipurile pe care nu vrei să le primești — numere de card, adrese de email, telefoane.
Nu-ți pune niciodată valoarea găsită în loguri — îți spune doar ce tip de dată a apărut, nu numărul de card în sine.
Rate limiting
Limitează câte cereri poate face cineva într-un interval. Limitele se definesc din dashboard: le dai un nume, o fereastră și un plafon.
| Câmp | Ce înseamnă |
|---|---|
| Nume | identitatea limitei. Fiecare nume are contorul lui — două limite cu același nume s-ar amesteca |
| Fereastră | intervalul pe care se numără: de la o secundă la 24 de ore |
| Plafon | câte cereri sunt permise în interval |
Poți pune până la 10 limite pe o cheie. Fiecare e o verificare în plus pe fiecare cerere protejată, deci nu e o listă de configurare, e un buget de latență.
Implicit, limita numără pe adresă IP. Pentru rute unde utilizatorul e deja logat, e mai corect să numeri pe utilizator — altfel colegi din aceeași rețea (birou, școală) se blochează reciproc:
await security.protect(request, { fingerprint: `user:${session.userId}` });Liste de IP-uri
Blochează adrese și intervale, sau scutește-le complet.
| Listă | Ce face |
|---|---|
| Blocate | adresele de aici sunt refuzate înainte de orice altceva |
| De încredere | adresele de aici sar peste toate capabilităților — nu doar peste blocare |
Acceptă o adresă exactă (203.0.113.7) sau un interval CIDR (203.0.113.0/24), IPv4 și IPv6.
Când o adresă e pe ambele liste, câștigă încrederea — așa poți avea un interval blocat larg cu
excepții înguste.
Challenge
Cere browserului să demonstreze, printr-un mic calcul, că nu e un simplu script. Din dashboard reglezi cât de greu e calculul și cât timp rămâne valabilă dovada. Are pagina lui: Protecția înregistrării.
Cum le montezi în cod
Partea asta se scrie o singură dată. consoleRules aduce toate protecțiile de mai sus, cu
setările tale din dashboard — nu trebuie să le enumeri și nu trebuie să revii aici când
schimbi ceva în panou:
import {
HazeloftSecurity,
consoleRules,
createConfigClient,
createEventReporter,
} from "@hazeloft/security";
export const security = new HazeloftSecurity({
apiKey: process.env.HAZELOFT_SECURITY_API_KEY,
configClient: createConfigClient(),
eventReporter: createEventReporter(),
rules: consoleRules,
});Challenge-ul cere două lucruri de la tine
Sunt singurele pe care dashboard-ul nu le poate cunoaște: secretul cu care se semnează dovezile și locul unde ții evidența celor deja folosite (ca aceeași dovadă să nu fie refolosită). I le dai o dată, restul rămâne în panou:
rules: (config) =>
consoleRules(config, {
challenge: {
secret: process.env.HAZELOFT_CHALLENGE_SECRET,
action: "sign-up",
isFresh: consumeNonce, // marchează dovada ca folosită; a doua oară întoarce false
},
}),Iar în endpointul care EMITE dovezile, ia dificultatea și durata tot din dashboard:
import { challengeIssueOptions, issueChallenge } from "@hazeloft/security";
const config = await configClient.get();
const issued = issueChallenge({
...challengeIssueOptions(config), // dificultatea + durata, din dashboard
secret: process.env.HAZELOFT_CHALLENGE_SECRET,
action: "sign-up",
});