Cum să configurezi verificarea emailului utilizatorului după înregistrare?
Știi cum toate aceste site-uri web trimit link-uri noilor utilizatori pentru a-și verifica adresa de email? Încerc să configurez ceva similar, dar după câteva cercetări încă nu am găsit o explicație bună despre cum să implementez acest lucru.
Sunt deschis pentru recomandări de plugin-uri, totuși majoritatea plugin-urilor pe care le-am găsit au o mulțime de alte funcționalități de care nu am nevoie cu adevărat.
Fără a utiliza un plugin, cum aș putea să adaug această funcționalitate în codul meu?
Abordarea mea ar fi să adaug un atribut 'Email neverificat' în meta-datele utilizatorului după înregistrare și să trimit un email cu un fel de cheie de verificare către utilizator. Cum pot verifica totuși dacă utilizatorul a făcut click pe acel link?
Mulțumesc pentru orice sfat

Poți utiliza hook-ul user_register
add_action( 'user_register', 'my_registration', 10, 2 );
function my_registration( $user_id ) {
// obține datele utilizatorului
$user_info = get_userdata($user_id);
// creează un cod md5 pentru verificare ulterioară
$code = md5(time());
// transformă-l într-un cod pentru a-l trimite utilizatorului prin email
$string = array('id'=>$user_id, 'code'=>$code);
// creează codul de activare și starea de activare
update_user_meta($user_id, 'account_activated', 0);
update_user_meta($user_id, 'activation_code', $code);
// creează URL-ul
$url = get_site_url(). '/my-account/?act=' .base64_encode( serialize($string));
// aici vom edita pentru a face acest lucru mai frumos
$html = 'Te rugăm să dai click pe următoarele linkuri <br/><br/> <a href="'.$url.'">'.$url.'</a>';
// trimite un email către utilizator
wp_mail( $user_info->user_email, __('Subiect Email','text-domain') , $html);
}
Poți verifica $_GET['act']
și apoi să activezi dacă este o cheie validă prin actualizarea valorii meta account_activated
. Poți utiliza hook-ul wp_authenticate_user
pentru a verifica starea de activare de fiecare dată când utilizatorul încearcă să se autentifice.
Fragment de cod pentru validare:
add_action( 'init', 'verify_user_code' );
function verify_user_code(){
if(isset($_GET['act'])){
$data = unserialize(base64_decode($_GET['act']));
$code = get_user_meta($data['id'], 'activation_code', true);
// verifică dacă codul dat este același cu al nostru
if($code == $data['code']){
// actualizează metadatele utilizatorului
update_user_meta($data['id'], 'is_activated', 1);
wc_add_notice( __( '<strong>Succes:</strong> Contul tău a fost activat! ', 'text-domain' ) );
}
}
}

Băieți, cred că metoda de mai sus introduce vulnerabilități de securitate care nu ar trebui să existe.
Scopul principal al verificării prin email este să ne asigurăm că persoanele care se înregistrează furnizează o adresă de email reală pe care o dețin sau măcar la care au acces. Nu vrem ca oamenii să se înregistreze cu o adresă de email aleatorie care aparține altcuiva, de exemplu adresa voastră de email.
Codul de mai sus are vulnerabilități care ar putea permite unui hacker să se înregistreze cu o adresă de email aleatorie care aparține altcuiva și apoi să găsească relativ ușor prin forță brută valoarea $user_id și valoarea $code pe pagina de verificare prin email.
Prima vulnerabilitate
Folosiți $user_id. Știu că această valoare poate fi orice, dar de obicei este un număr întreg, mai ales dacă folosiți WordPress, care este folosit de circa 30% din site-urile de pe internet, iar uitându-ne la codul PHP de mai sus, acesta este într-adevăr bazat pe WordPress. Hacker-ului fie i se oferă $user_id-ul său ca parte a procesului de înregistrare, fie își ghicește $user_id prin forță brută mergând secvențial începând cu numărul 1 și continuând 2, 3, 4, 5, 6... își vor ghici $user_id în mai puțin de o zi, poate chiar în mai puțin de o oră dacă site-ul vostru nu are mulți membri.
A doua vulnerabilitate
Creați un $code folosind funcția de hash MD5 și ora înregistrării. Hacker-ul știe la ce oră s-a înregistrat. Să presupunem că hacker-ul se înregistrează la ora 15:00. Acum tot ce trebuie să facă hacker-ul este să facă hash MD5 pentru orele de la 14:55 la 15:05 și vor ghici $code în mai puțin de o oră.
Având în vedere cele de mai sus, hacker-ul poate pur și simplu să găsească prin forță brută $user_id și $code în mai puțin de o zi și să verifice o adresă de email pe care nu o deține
tut tut tut
O abordare mai bună ar fi să generați un $code cu funcția rand() folosind litere mari (A-Z), litere mici (a-z), cifre (0-9) și caractere speciale, de ex. (!&#). Acea funcție de hash MD5 folosește doar cifrele 0-9 și literele mici a-f, iar modul în care o folosiți bazat pe ora înregistrării o face incredibil de ușor de redus și de atacat prin forță brută.
Am scris codul PHP de mai jos pentru a genera un $code aleator cu Litere Mari/Litere Mici/Cifre/Caractere Speciale. Nu le faceți atât de ușor hackerilor, băieți.
function generateRandomString($stringLength){
//specifică caracterele care vor fi folosite pentru generarea șirului aleator, nu include caractere pe care WordPress nu le permite la creare
$characters = "0123456789ABCDEFGHIJKLMNPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz_[]{}!@$%^*().,>=-;|:?";
//obține lungimea totală a caracterelor specificate pentru generarea șirului aleator
$charactersLength = strlen($characters);
//declară un șir pe care îl vom folosi pentru a crea șirul aleator
$randomString = '';
for ($i = 0; $i < $stringLength; $i++) {
//generează caractere aleatorii
$randomCharacter = $characters[rand(0, $charactersLength - 1)];
//adaugă caracterele aleatorii la șirul aleator
$randomString .= $randomCharacter;
};
//sanitize_user, pentru orice eventualitate
$sanRandomString = sanitize_user($randomString);
//verifică dacă șirul aleator conține Litere Mari/Litere Mici/Cifre/Caractere Speciale și dacă are lungimea corectă
if ( (preg_match('([a-zA-Z].*[0-9]|[0-9].*[a-zA-Z].*[_\W])', $sanRandomString)==1) && (strlen($sanRandomString)==$stringLength) )
{
//returnează șirul aleator dacă îndeplinește criteriile de complexitate
return $sanRandomString;
} else {
//dacă șirul aleator nu îndeplinește criteriile minime, apelează funcția din nou
return call_user_func("generateRandomString",($stringLength) );
}
}//sfârșitul funcției generateRandomString
//apelează funcția pentru a genera un șir aleator cu Litere Mari/Litere Mici/Cifre/Caractere Speciale
//în funcție transmitem lungimea șirului necesar, în acest exemplu va genera un șir de 32 de caractere
$code = generateRandomString(32);
echo $code;

Răspuns excelent! Ar fi fost chiar și mai bine dacă ai fi formatat puțin codul. În plus, caracterul $ trebuie scăpat. De asemenea, corectează-mă dacă greșesc, dar nu există niciun motiv să folosești call_user_func
în loc să apelezi funcția direct.

Motivul pentru care folosesc call_user_function este că funcția creează un șir aleatoriu de orice lungime specifici. În cazul în care criteriile de complexitate ale șirului aleatoriu nu sunt îndeplinite, funcția se va executa din nou automat, de exemplu dacă funcția a generat un șir aleatoriu care nu conținea o literă majusculă sau un număr, atunci call_user_function execută funcția din nou. Funcția va returna un șir aleatoriu doar atunci când îndeplinește toate criteriile de complexitate.

Am testat folosind base_64_encode pe $code generat de funcția de șir aleatoriu atașat la $url, apoi l-am preluat cu metoda GET fără probleme.

De asemenea, este o idee foarte proastă să trimiteți direct $code către get_user_meta, deoarece este același lucru ca și stocarea unei parole în text simplu într-o bază de date. Ar trebui să criptați $code stocat în get_user_meta. Apoi să decriptați folosind $code atașat la $url. Altfel, ați ocolit complet scopul securității WordPress de hash-uit a parolelor. Uitați-vă la wp-users, nicio parolă nu este stocată în text simplu, așa că trebuie să hash-uiți și $code pentru resetarea parolei înainte de stocare. Folosiți funcția password_hash() pentru criptare și password_verify() pentru decriptare.

Nu cred că un cod de activare a utilizatorului trebuie neapărat hash-uit pentru a fi securizat. Dacă cineva accesează baza ta de date, codurile de activare ale utilizatorilor nu contează cu adevărat, ei pot pur și simplu să seteze emailul ca confirmat, deși probabil au în minte lucruri mult mai grave. Referitor la call_user_function
, încă nu înțeleg de ce nu poți apela pur și simplu funcția din ea însăși. O funcție nu se poate auto-apela în PHP?

Da, funcția este apelată direct în codul de mai sus la final unde scrie "$code = generateRandomString(32);". Funcția folosește preg_match pentru a verifica dacă șirul aleator generat are Litere Mari/Litere Mici/Numere/Caractere Speciale. Dacă șirul aleator nu îndeplinește criteriile de complexitate, call_user_function execută automat funcția din nou. Funcția va continua să genereze șiruri aleatoare până când unul dintre ele îndeplinește criteriile de complexitate specificate în preg_match. Primul șir aleator ar putea fi "abcdefghijklmnopqrstuvwxyzabcdef"

"abcdefghijklmnopqrstuvwxyzabcdef" nu îndeplinește cerințele de complexitate, deoarece nu conține numere, litere mari sau caractere speciale, așa că call_user_function apelează automat funcția din nou până când obținem un șir aleatoriu care îndeplinește cerințele de complexitate. Acționează ca o buclă.

Sunt curios de ce, dacă WordPress hash-uieste parola contului în baza de date, nu ai hash-ui și cheia de resetare pentru aceeași parolă?

Crezi că WordPress nu ar trebui să hash-uiască parolele conturilor în baza de date?
