Come impostare la verifica dell'email utente dopo la registrazione?

30 giu 2018, 11:00:23
Visualizzazioni: 26.2K
Voti: 10

Sai come tutti questi siti web inviano link ai loro nuovi utenti per verificare il loro indirizzo email? Sto cercando di impostare qualcosa di simile ma dopo alcune ricerche non ho ancora trovato una buona spiegazione su come implementarlo.

Sono aperto a suggerimenti sui plugin, tuttavia la maggior parte dei plugin che ho trovato hanno una tonnellata di altre funzionalità di cui non ho realmente bisogno.

Senza utilizzare un plugin, come potrei aggiungere questa funzionalità al mio codice?

Il mio approccio sarebbe quello di aggiungere un attributo 'Email non verificata' ai meta dati dell'utente dopo la registrazione e inviare un'email con una chiave di verifica all'utente. Come posso verificare se l'utente ha effettivamente cliccato su quel link?

Grazie per qualsiasi consiglio

0
Tutte le risposte alla domanda 2
2
12

Puoi utilizzare l'hook user_register

add_action( 'user_register', 'my_registration', 10, 2 );
function my_registration( $user_id ) {
    // ottieni i dati dell'utente
    $user_info = get_userdata($user_id);
    // crea un codice md5 da verificare successivamente
    $code = md5(time());
    // crea un codice da inviare all'utente via email
    $string = array('id'=>$user_id, 'code'=>$code);
    // crea il codice di attivazione e lo stato di attivazione
    update_user_meta($user_id, 'account_activated', 0);
    update_user_meta($user_id, 'activation_code', $code);
    // crea l'URL
    $url = get_site_url(). '/my-account/?act=' .base64_encode( serialize($string));
    // modificheremo qui per renderlo più elegante
    $html = 'Clicca sui seguenti link <br/><br/> <a href="'.$url.'">'.$url.'</a>';
    // invia un'email all'utente
    wp_mail( $user_info->user_email, __('Oggetto dell\'email','text-domain') , $html);
}

Puoi controllare $_GET['act'] e poi attivare l'account se si tratta di una chiave valida aggiornando il valore meta account_activated. Puoi utilizzare l'hook wp_authenticate_user per verificare lo stato di attivazione ogni volta che un utente tenta di effettuare il login.

Frammento per la validazione:

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);
        // verifica se il codice fornito corrisponde al nostro
        if($code == $data['code']){
            // aggiorna il meta dell'utente
            update_user_meta($data['id'], 'is_activated', 1);
            wc_add_notice( __( '<strong>Successo:</strong> Il tuo account è stato attivato! ', 'text-domain' )  );
        }
    }
}
30 giu 2018 12:22:54
Commenti

Grazie, questo è davvero utile! Una cosa però, come posso accedere all'User ID e al $code dall'url? Sicuramente devo decodificarlo in qualche modo?

Philipp K Philipp K
30 giu 2018 12:53:41

Ho aggiornato la risposta :)

Akshat Akshat
30 giu 2018 13:01:22
10

Ragazzi, penso che il metodo sopra menzionato introduca vulnerabilità di sicurezza che non dovrebbero esserci.

L'obiettivo principale della verifica email è assicurarci che le persone che si registrano forniscano un indirizzo email reale di cui sono proprietari o almeno a cui hanno accesso. Non vogliamo che le persone si registrino con, diciamo, un indirizzo email casuale di proprietà di qualcun altro, per esempio il vostro indirizzo email.

Il codice sopra presenta vulnerabilità che potrebbero permettere a un hacker di registrare un indirizzo email casuale di proprietà di qualcun altro e poi forzare abbastanza facilmente i valori $user_id e $code nella pagina di verifica email.

1a vulnerabilità

State usando $user_id. So che questo valore potrebbe essere qualsiasi cosa, ma tipicamente sarà un intero, specialmente se usate WordPress, che è circa il 30% dei siti internet, e guardando il codice PHP sopra, è effettivamente basato su WordPress. L'hacker riceve il suo $user_id come parte del processo di registrazione oppure lo indovina tramite brute force, semplicemente procedendo in sequenza partendo dal numero 1 e continuando con 2, 3, 4, 5, 6... Indovinerà il suo $user_id in meno di un giorno, forse anche in meno di un'ora se il vostro sito non ha molti membri.

2a vulnerabilità

State creando un $code usando la funzione di hash MD5 e l'ora di registrazione. L'hacker sa a che ora si è registrato. Diciamo che l'hacker si registra alle 15:00. Ora tutto ciò che deve fare è fare l'hash MD5 degli orari dalle 14:55 alle 15:05 e forzerà il $code in meno di un'ora.

Considerando quanto sopra, l'hacker può semplicemente forzare $user_id e $code in meno di un giorno e verificare un indirizzo email di cui non è proprietario

tsk tsk tsk

Un approccio migliore sarebbe generare un $code con la funzione rand() usando maiuscole (A-Z), minuscole (a-z), numeri (0-9) e caratteri speciali es. (!&#). Quella funzione di hash MD5 usa solo numeri 0-9 e lettere minuscole a-f e il modo in cui la state usando, basandovi sull'ora di registrazione, lo rende incredibilmente facile da restringere e attaccare con brute force.

Ho scritto il seguente codice PHP per generare un $code casuale con Lettere Maiuscole/Minuscole/Interi/Caratteri Speciali. Non rendetela così facile per gli hacker, ragazzi.

function generateRandomString($stringLength){
    //specifica i caratteri da usare per generare la stringa casuale, non includere caratteri che WordPress non permette nella creazione
    $characters = "0123456789ABCDEFGHIJKLMNPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz_[]{}!@$%^*().,>=-;|:?";

    //ottieni la lunghezza totale dei caratteri specificati da usare per generare la stringa casuale
    $charactersLength = strlen($characters);

    //dichiara una stringa che useremo per creare la stringa casuale
    $randomString = '';

    for ($i = 0; $i < $stringLength; $i++) {
        //genera caratteri casuali
        $randomCharacter = $characters[rand(0, $charactersLength - 1)];
        //aggiungi i caratteri casuali alla stringa casuale
        $randomString .=  $randomCharacter;
    };

    //sanitize_user, per sicurezza
    $sanRandomString = sanitize_user($randomString);

    //controlla che la stringa casuale contenga Maiuscole/Minuscole/Interi/Caratteri Speciali e che abbia la lunghezza corretta
    if ( (preg_match('([a-zA-Z].*[0-9]|[0-9].*[a-zA-Z].*[_\W])', $sanRandomString)==1) && (strlen($sanRandomString)==$stringLength) )
    {
        //restituisce la stringa casuale se soddisfa i criteri di complessità
        return $sanRandomString;
    } else {
        //se la stringa casuale non soddisfa i criteri minimi, richiama la funzione
        return call_user_func("generateRandomString",($stringLength) );
    }
}//fine della funzione generateRandomString

//chiama la funzione per generare una stringa casuale con Lettere Maiuscole/Minuscole/Interi/Caratteri Speciali
//nella funzione passiamo la lunghezza della stringa richiesta, in questo esempio genererà una stringa di 32 caratteri
$code = generateRandomString(32);

echo $code;
12 apr 2020 16:43:40
Commenti

Ottima risposta! Sarebbe ancora un po' migliore se formattassi un po' il codice. Inoltre il $ deve essere escapato. Inoltre, correggimi se sbaglio, ma non c'è motivo di usare call_user_func invece di chiamare direttamente la funzione.

Slbox Slbox
15 apr 2020 03:25:54

Il motivo per cui uso call_user_function è che la funzione crea una stringa casuale della lunghezza specificata. Nel caso in cui i criteri di complessità della stringa casuale non siano soddisfatti, la funzione verrà semplicemente eseguita nuovamente automaticamente, ad esempio se la funzione generasse una stringa casuale che non contiene una lettera maiuscola o un numero, allora call_user_function esegue nuovamente la funzione. La funzione restituirà una stringa casuale solo quando soddisfa tutti i criteri di complessità.

User User
15 apr 2020 20:40:21

Ho testato l'uso di base_64_encode sul $code generato dalla funzione di stringa casuale allegata a $url e poi recuperato con il metodo GET senza problemi.

User User
15 apr 2020 20:48:00

Anche l'idea di inviare direttamente il $code a get_user_meta è molto negativa, poiché equivale a memorizzare password in testo semplice in un database. Dovresti crittografare il $code memorizzato in get_user_meta. Poi decrittare utilizzando il $code allegato all'$url. Altrimenti hai completamente bypassato il punto principale della sicurezza di hashing delle password di WordPress. Guarda la tua tabella wp-users, nessuna password è memorizzata in testo semplice, quindi devi anche fare l'hash del $code per il reset della password prima di memorizzarlo. Usa la funzione password_hash() per crittografare e password_verify() per decrittare.

User User
15 apr 2020 21:00:31

Non credo che un codice di attivazione utente debba necessariamente essere sottoposto ad hashing per essere sicuro. Se qualcuno accede al tuo database, i codici di attivazione utente non contano davvero, possono semplicemente impostare l'email come confermata, anche se probabilmente hanno in mente cose molto peggiori. Riguardo a call_user_function, ancora non capisco perché non puoi semplicemente chiamare la funzione da se stessa. Una funzione non può chiamare se stessa in PHP?

Slbox Slbox
15 apr 2020 22:16:50

Sì, la funzione viene chiamata direttamente nel codice sopra dove dice "$code = generateRandomString(32);". La funzione utilizza preg match per verificare se la stringa casuale generata ha Lettere Maiuscole/Lettere Minuscole/Numeri/Caratteri Speciali. Se la stringa casuale non soddisfa i criteri di complessità, call_user_function esegue automaticamente nuovamente la funzione. La funzione continuerà a generare stringhe casuali finché una di esse non soddisfa i criteri di complessità specificati nel preg match. La prima stringa casuale potrebbe essere "abcdefghijklmnopqrstuvwxyzabcdef"

User User
15 apr 2020 23:52:02

"abcdefghijklmnopqrstuvwxyzabcdef" non soddisfa i requisiti di complessità in quanto non contiene numeri, lettere maiuscole o caratteri speciali, quindi call_user_function richiama automaticamente la funzione finché non otteniamo una stringa casuale che soddisfi i requisiti di complessità. Si comporta come un ciclo.

User User
15 apr 2020 23:53:27

Mi chiedo perché, se WordPress esegue l'hash della password dell'account nel database, non venga eseguito l'hash anche della chiave di reset per quella stessa password?

User User
15 apr 2020 23:55:17

Pensi che WordPress non dovrebbe eseguire l'hash delle password degli account nel database?

User User
15 apr 2020 23:56:29

@MikeMoy Ho appena visto la tua risposta e mi piacerebbe molto utilizzare il tuo codice, se possibile. Dovrei usarlo insieme alle prime 2 azioni della prima risposta, oppure andrebbe a sostituire parte del codice della prima risposta?

Joe Bloggs Joe Bloggs
7 mag 2021 11:00:39
Mostra i restanti 5 commenti