Cum să configurezi verificarea emailului utilizatorului după înregistrare?

30 iun. 2018, 11:00:23
Vizualizări: 26.2K
Voturi: 10

Ș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

0
Toate răspunsurile la întrebare 2
2
12

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' )  );
        }
    }
}
30 iun. 2018 12:22:54
Comentarii

Mulțumesc, asta chiar mă ajută! Totuși, o întrebare: cum pot accesa ID-ul utilizatorului și codul $code din URL? Presupun că trebuie să-l decodific cumva, nu?

Philipp K Philipp K
30 iun. 2018 12:53:41

Am actualizat răspunsul :)

Akshat Akshat
30 iun. 2018 13:01:22
10

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;
12 apr. 2020 16:43:40
Comentarii

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.

Slbox Slbox
15 apr. 2020 03:25:54

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.

User User
15 apr. 2020 20:40:21

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.

User User
15 apr. 2020 20:48:00

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.

User User
15 apr. 2020 21:00:31

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?

Slbox Slbox
15 apr. 2020 22:16:50

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"

User User
15 apr. 2020 23:52:02

"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ă.

User User
15 apr. 2020 23:53:27

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ă?

User User
15 apr. 2020 23:55:17

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

User User
15 apr. 2020 23:56:29

@MikeMoy Tocmai am dat peste răspunsul tău și mi-ar plăcea foarte mult să folosesc codul tău, dacă este în regulă. Ar trebui să-l folosesc împreună cu primele 2 acțiuni din primul răspuns sau ar înlocui vreun cod din primul răspuns?

Joe Bloggs Joe Bloggs
7 mai 2021 11:00:39
Arată celelalte 5 comentarii