‫Istruttore: Quindi in
‫questa lezione, gestiremo le password dei nostri utenti nel database.
‫E con ciò intendo prima
‫convalidare se la password immessa è uguale alla password
‫confermata e quindi anche crittografare la password nel database
‫per proteggerla dagli attacchi.
‫E quindi la prima cosa
‫che faremo è convalidare se le due password immesse sono le stesse.
‫E il posto migliore per
‫farlo è qui nella conferma della password, ok?
‫E quindi scriviamo il nostro validatore personalizzato per quello, va bene?
‫Quindi ricorda, usiamo la proprietà validate e quindi,
‫poiché vogliamo creare una funzione
‫e anche un messaggio di errore, apriamo un nuovo oggetto
‫qui e poi lì creiamo validatore,
‫che sarà la
‫funzione e iniziamo effettivamente con questo.
‫Quindi, ricorda, tutto ciò di cui abbiamo bisogno qui
‫è specificare una semplice funzione di callback che verrà quindi chiamata
‫quando verrà creato il nuovo documento.
‫Quindi, funzione, e
‫anche qui, non possiamo usare una funzione freccia perché in
‫realtà abbiamo bisogno di usare la parola chiave disk.
‫Bene?
‫Quindi, ricorda che dalla funzione di convalida
‫restituiamo vero o falso
‫e se il valore restituito è
‫falso, significa che otterremo un errore di convalida, ok?
‫E, naturalmente, se è vero, allora no.
‫E quindi quello che vogliamo qui è dire che l'elemento corrente so,
‫password confirm, è uguale a questa password con punto, quindi, password
‫confirm, è uguale a questa password con punto,
‫ed è proprio così!
‫Quindi, ad esempio, se la conferma della password è
‫A-B-C e anche la password è
‫A-B-C, questo ovviamente tornerà vero, ok?
‫E quindi la convalida viene
‫passata e non si verificherà alcun errore.
‫Ma, se la password iniziale è, diciamo, X-Y-Z, allora
‫ovviamente questo tornerà falso
‫e avremo un errore di convalida, ok?
‫Quindi, molto semplice, ma dobbiamo tenere
‫a mente che funzionerà solo sul salvataggio, ok?
‫Ne ho parlato prima
‫quando abbiamo usato il validatore personalizzato sul modello del tour, giusto?
‫Ma te lo sto ricordando
‫di nuovo qui perché questo è assolutamente cruciale qui a questo punto, ok?
‫Quindi lascia che te lo scriva qui.
‫(clic
‫sulla tastiera)
‫Al salvataggio.
‫Bene?
‫E per questo, ogni volta che vorremo aggiornare un
‫utente, dovremo sempre usare anche il salvataggio e
‫non, ad esempio, trovarne uno e aggiornarlo come abbiamo
‫fatto con i nostri tour, ok?
‫Quindi teniamolo a mente
‫quando scriviamo il resto del codice nel resto
‫della sezione e soprattutto per l'aggiornamento, ok?
‫Perché diciamo che abbiamo aggiornato la password dell'utente
‫semplicemente con un aggiornamento regolare.
‫Quindi, in tal caso, questa password conferma
‫la convalida che abbiamo qui non funzionerebbe più, ok?
‫E ovviamente questo non può succedere, ok?
‫E quindi, ancora una volta, tieni presente che funzionerà
‫solo quando creiamo un nuovo oggetto, quindi su dot create o su save.
‫Bene?
‫Quindi, su crea e
‫salva, quindi, su crea e salva, va
‫bene?
‫Quindi creiamo un nuovo oggetto usando create, giusto?
‫Quindi, proprio qui, abbiamo usato un punto create Quindi,
‫proprio qui, abbiamo usato un
‫punto create ma
‫ricordate come vi ho anche mostrato che possiamo usare
‫un salvataggio punto dell'utente, come questo, giusto?
‫E in effetti, possiamo anche usare un punto
‫di salvataggio dell'utente per aggiornare l'utente, ok?
‫Ma di nuovo, ne parleremo un po' più tardi.
‫Bene?
‫Quindi ora proviamo questa convalida qui, ok?
‫Quindi, prima di tutto, proviamo a
‫creare un nuovo utente con
‫questi dati qui che non dovrebbe funzionare perché
‫abbiamo già un utente con questo indirizzo email e abbiamo detto
‫che questo dovrebbe essere unico e quindi
‫non dovrebbe funzionare.
‫Ok, e quindi ovviamente il nostro errore di chiave duplicata, giusto?
‫Ora, se fossi in
‫produzione, ovviamente otterremmo già il nostro errore ben
‫formattato che abbiamo creato nell'ultima sezione, giusto?
‫Ma in questo momento siamo in fase di sviluppo e quindi questo è l'errore che
‫abbiamo definito che vogliamo vedere.
‫Bene?
‫Quindi usiamo semplicemente un'altra e-mail qui
‫e poiché stiamo lavorando sull'e-mail
‫qui, vediamo anche come funziona la convalida dell'indirizzo e-mail.
‫Quindi diciamo che abbiamo specificato questo come nostra email.
‫E così, vediamo l'errore "fornisci un'email valida. " Bene?
‫Quindi proviamolo in questo modo perché penso che anche
‫questo non dovrebbe essere valido.
‫Forse lo è, ma vediamo.
‫E sì, in realtà non è
‫perché non ci sono nomi di dominio con una sola lettera, ok?
‫E quindi questo validatore è piuttosto specifico,
‫quindi è davvero buono.
‫Ora, se lo facciamo in questo modo, ovviamente dovrebbe funzionare.
‫Ma comunque, quello che
‫volevamo testare qui sono queste diverse password, ok?
‫E ora ricordo che
‫in realtà non abbiamo creato un messaggio di errore, credo.
‫E sì, non l'abbiamo fatto.
‫E quindi, aggiungiamo anche questo qui.
‫Quindi messaggio, non
‫sono la stessa
‫cosa.
‫Bene.
‫Quindi aggiungiamo qualcosa qui, non importa.
‫E quindi ora le password non sono le stesse, ok?
‫Così perfetta.
‫E ora, naturalmente, la nostra convalida dovrebbe essere passata.
‫E infatti, lo è e abbiamo creato il nostro nuovo utente.
‫Andiamo su Compass qui, diamo
‫un'occhiata e poi effettivamente lo eliminiamo in modo
‫che io possa in seguito creare più utenti con la stessa email.
‫Tutto ok?
‫E comunque non vogliamo tutta questa
‫spazzatura qui, quindi tutti questi utenti di prova, ok?
‫Ma ora, il prossimo passo è crittografare effettivamente queste
‫semplici password che stiamo memorizzando nel
‫nostro database in questo momento.
‫Quindi, come ho detto nell'ultimo
‫video, quando lavoriamo
‫con l'autenticazione, uno dei principi
‫fondamentali è non archiviare mai password semplici in un database, ok?
‫Quindi è qualcosa che non è assolutamente accettabile, ok?
‫Quindi dovremmo sempre crittografare le password degli utenti perché
‫immaginiamo che per qualche
‫motivo un hacker ottenga l'accesso al database.
‫Se poi le password sono memorizzate in testo normale lì dentro,
‫allora può semplicemente accedere come qualsiasi utente e
‫poi fare quello che vuole
‫veramente e causare molti danni in alcuni casi, ok?
‫E quindi dobbiamo assolutamente impedirlo.
‫E quindi ora andiamo avanti e implementiamo questo.
‫Ora, qual è il posto migliore per farlo davvero?
‫Bene, direi che il modello è sempre il posto
‫migliore per fare questo tipo di funzionalità.
‫Quindi, in questo caso, la crittografia
‫perché ha davvero a che fare con i dati
‫stessi e quindi dovrebbe essere
‫sul modello e non nel controller, ok?
‫Quindi, di nuovo, tieni a mente i modelli grassi
‫e la filosofia dei controller sottili.
‫Tutto ok?
‫Quindi, come implementeremo ora questa crittografia?
‫Bene, questo è un altro caso d'uso
‫perfetto per l'utilizzo del middleware Mongoose.
‫E quello che
‫useremo è un middleware pre-salvataggio.
‫Quindi in pratica il middleware per documenti, ok?
‫Quindi, ricorda che l'abbiamo definito sullo schema, ok?
‫E in questo caso, vogliamo impostare
‫un pre-hook, quindi un pre-middleware al salvataggio, va bene?
‫quindi un pre-middleware sul salvataggio, va bene?
‫E il motivo per cui lo
‫stiamo facendo in questo
‫modo è che la funzione middleware che specificheremo qui,
‫quindi la crittografia, avverrà tra il momento
‫in cui riceviamo quei dati e il
‫momento in cui sono effettivamente persistenti al banca dati, ok?
‫Ecco dove viene eseguito il middleware di pre-salvataggio.
‫Tra ottenere i dati e salvarli nel database.
‫E quindi questo è il momento perfetto per manipolare i dati.
‫Tutto ok?
‫Quindi,
‫una funzione, quindi ricordiamo che abbiamo accesso
‫alla funzione successiva per chiamare il prossimo middleware.
‫Ok, ora vogliamo crittografare la password solo
‫se il campo della password è stato effettivamente aggiornato, ok?
‫Quindi in pratica solo quando la password viene effettivamente cambiata o anche
‫quando ne viene creata una nuova, ok?
‫Perché immagina che l'utente stia solo aggiornando l'e-mail.
‫Quindi in tal
‫caso, ovviamente, non vogliamo crittografare di nuovo la password, giusto?
‫E così possiamo farlo con Mongoose.
‫E quindi diremo, se e poi questo, che si
‫riferisce al documento attuale, giusto?
‫E così in questo caso, all'utente corrente
‫e poi viene modificato.
‫Bene?
‫Quindi abbiamo un metodo su tutti i documenti che possiamo
‫usare se un determinato campo è stato modificato.
‫E quindi qui, dobbiamo passare nel nome del campo,
‫quindi "password. " Bene?
‫E quindi fondamentalmente, quello che vogliamo fare
‫qui è dire che se la password non è stata
‫modificata, quindi no, allora in quel caso, torniamo semplicemente da
‫questa funzione e non eseguiamo nessuno degli altri codici
‫che sono qui e quindi
‫chiamiamo il prossimo middleware.
‫Bene?
‫Quindi, di nuovo, se la password non è stata modificata,
‫usciamo da questa funzione
‫e chiamiamo il prossimo middleware.
‫Altrimenti eseguiremo il codice
‫che inserirò qui.
‫E quindi ora è finalmente giunto il momento
‫di crittografare effettivamente o, come possiamo anche dire, di eseguire l'hash della password, ok?
‫Quindi vedrai il termine "hash" o "hashing" tutto
‫il tempo e quindi in pratica significa anche crittografia, ok?
‫Ora faremo questa crittografia, o hashing, usando
‫un algoritmo di hashing molto
‫noto e ben studiato e molto popolare chiamato bcrypt.
‫Bene?
‫Quindi questo algoritmo prima salterà e poi eseguirà l'hashing della
‫nostra password per renderla davvero forte per proteggerla
‫dagli attacchi di forza bruta, ok?
‫E quindi questa è l'intera
‫ragione per cui la crittografia deve essere davvero forte.
‫Perché gli attacchi di forza bruta potrebbero
‫provare a indovinare una certa password se non è molto crittografata.
‫E ricorda come ho detto che bcrypt salirà la nostra password
‫e questo significa solo che aggiungerà una stringa
‫casuale alla password in modo che due password uguali
‫non generino lo stesso hash, ok?
‫Ha senso?
‫Ora non entrerò nei dettagli crittografici su come funziona
‫davvero dietro le quinte e perché
‫abbiamo bisogno di un sistema così complesso, ok?
‫Ma ovviamente puoi leggere tutto quello che vuoi su bcrypt online.
‫C'è davvero un sacco di cose interessanti
‫da scoprire lì, va bene?
‫Ad ogni modo, ora andiamo avanti e utilizziamo il pacchetto
‫bcrypt js per utilizzare questo algoritmo.
‫Quindi, quindi
‫npm installa
‫quindi npm installa
‫bcryptjs.
‫Bene?
‫E quindi questa è fondamentalmente un'implementazione bcrypt
‫per Javascript.
‫Bene?
‫Torniamo al nostro terminale principale e poi
‫andiamo avanti e importiamolo qui.
‫E questo per impostazione predefinita è chiamato solo bcrypt, ok?
‫E non bcryptjs.
‫(clic sulla tastiera) Va
‫bene.
‫Tutto bene.
‫E ora, usiamolo davvero.
‫Quindi, vogliamo dire che questa password punto, quindi la
‫password corrente in questo documento dovrebbe
‫essere uguale a bcrypt dot hash dovrebbe essere
‫uguale a bcrypt dot hash e quindi la
‫nostra password corrente.
‫Bene?
‫E poi qui dobbiamo specificare un parametro di costo, ok?
‫E potremmo effettivamente farlo in due modi.
‫Quindi il primo modo sarà generare manualmente il sale, quindi
‫quella stringa casuale in pratica, che
‫verrà aggiunta alla nostra
‫password e quindi utilizzerà quel sale qui in questa funzione di hash.
‫Tutto ok?
‫Ma invece, per rendere le cose un
‫po' più semplici, possiamo anche semplicemente passare un parametro di costo
‫in questa funzione qui.
‫E quindi questa è fondamentalmente
‫una misura di quanto intensiva la CPU sarà questa operazione, ok?
‫E il valore predefinito qui credo sia 10, ma
‫in questo momento è un po' meglio usare 12
‫perché i computer sono diventati sempre più potenti.
‫Quindi, come 20 anni fa, avresti potuto usare otto qui e
‫poi un po' più tardi di 10,
‫ma in questo momento a questo punto nel tempo, è meglio usare 12.
‫Quindi più alto è questo
‫costo qui, fondamentalmente più intenso sarà il processo
‫per la CPU e migliore sarà la crittografia della password, ok?
‫E ovviamente potremmo andare ancora più
‫in alto, ma allora ci vorrebbe troppo tempo, va bene?
‫E te lo mostrerò in un secondo.
‫Bene?
‫Ma per ora,
‫finiamola perché c'è ancora una cosa qui.
‫Quindi questo hash qui è in realtà la versione
‫asincrona, ma esiste anche una versione sincrona.
‫Ma come già saprai, non vogliamo utilizzare
‫la versione sincrona
‫perché bloccherà il ciclo degli eventi e quindi impedirà ad
‫altri utenti di utilizzare l'applicazione.
‫Quindi, proprio come abbiamo imparato all'inizio.
‫E quindi ovviamente vogliamo
‫usare la versione asincrona che è questa.
‫E questo restituirà quindi
‫una promessa e quella promessa, ovviamente, dobbiamo aspettare.
‫Quindi, dobbiamo usare wait e poi dire che questa funzione
‫è una funzione asincrona, proprio come questa.
‫Quindi, ricapitoliamo qui.
‫Quindi, vogliamo impostare la nostra password corrente
‫fondamentalmente per crittografare questa versione della password originale con un costo di
‫12, per non rendere troppo
‫facile l'infrazione della password, ma anche per non far impiegare
‫troppo tempo all'applicazione per crittografare la password, Tutto ok?
‫Quindi, con questo, abbiamo crittografato la nostra
‫password e ora, alla fine, ciò
‫che dobbiamo fare è sostanzialmente eliminare la password di conferma, ok?
‫Perché in questo momento,
‫abbiamo solo la vera password hash, giusto?
‫Quindi, questa password del punto
‫conferma, quindi,
‫questa password del punto conferma, e come
‫in pratica eliminiamo il campo, quindi non essere
‫persistente nel database è impostarlo su undefined.
‫Tutto ok?
‫Quindi, abbiamo davvero solo bisogno di questa password confermata qui
‫per la convalida che abbiamo implementato prima.
‫Quindi, solo per assicurarsi che
‫l'utente abbia effettivamente inserito due password uguali
‫in modo da non commettere errori con la sua password.
‫Destra?
‫Quindi, dopo che questa convalida ha
‫avuto successo, in realtà non abbiamo più bisogno
‫di questo campo, quindi non vogliamo davvero mantenerlo nel database.
‫Ed è per questo che l'abbiamo semplicemente impostato qui su undefined.
‫Tutto ok?
‫Ora potresti chiederti perché funziona perché
‫in realtà impostiamo la conferma della password su
‫un valore richiesto, giusto?
‫Ma questo significa semplicemente che è un input richiesto,
‫non che è necessario che venga effettivamente mantenuto
‫nel database, ok?
‫al database, ok?
‫Ora, solo per finire, dobbiamo ovviamente chiamare anche il prossimo.
‫Bene?
‫Diamo un salvataggio.
‫E in realtà aggiungerò alcuni commenti
‫qui per renderlo davvero chiaro per te.
‫Quindi, in pratica, ciò che fa è eseguire questa
‫funzione
‫solo se la
‫password è stata effettivamente modificata.
‫Quindi qui,
‫hash la password con un costo di 12.
‫E poi,
‫elimina il campo di conferma della password.
‫Bene.
‫E ora, andiamo avanti e testiamo questo.
‫E ora creerò un nuovo utente con esattamente questi dati
‫e ora diamo un'occhiata al risultato.
‫E infatti, ora otteniamo questa password dall'aspetto molto strano che
‫in effetti è la versione crittografata di pass1234.
‫E inoltre, come vedi, la conferma della password non è più qui.
‫Bene?
‫E così, proprio così, ora abbiamo archiviato gli
‫utenti in modo sicuro nel nostro database.
‫Lascia che ora ti mostri come funzionerà se,
‫ad esempio, lo impostiamo su 16 qui.
‫E ho bisogno di cambiare l'e-mail qui.
‫E quindi ora dovrebbe volerci molto tempo e non
‫sono sicuro di poter aspettare.
‫Oh, in realtà ci sono voluti circa quattro secondi e mezzo.
‫Ma è ancora un po' troppo credo, ok?
‫Quindi, riportiamolo a
‫12
‫e dovrebbe andare meglio, ok?
‫E ora, di nuovo,
‫cancelliamo questi utenti che abbiamo appena creato.
‫E in realtà ho bisogno di sbarazzarmi
‫di questo primo perché questo ha ancora la password in chiaro.
‫E quindi questo utente non
‫funzionerà quando inizieremo ad accedere effettivamente agli
‫utenti in base alla loro password.
‫Bene?
‫Quindi liberiamoci di questo.
‫Bene?
‫E anche quello che volevo mostrarti
‫qui è che abbiamo inserito la stessa identica
‫password per questi due utenti che abbiamo creato, giusto?
‫Ma vedi che la
‫password crittografata è in realtà molto diversa, giusto?
‫E quindi questo è il potere di salare la
‫password prima di eseguirne l'hashing.
‫Tutto ok?
‫Quindi, proprio in questo modo, abbiamo, ancora una volta, implementato una gestione delle
‫password molto sicura e buona.