‫Jonas: Lassen Sie uns jetzt
‫unsere Middleware-Schutzfunktion weiterschreiben.
‫In der letzten Vorlesung haben wir also den
‫Token aus dem Authorization Header
‫gelesen und dann überprüft, ob der Token tatsächlich existiert.
‫Also gleich hier.
‫Und als nächstes haben wir den Verifizierungsschritt für das Token.
‫Und ich hoffe, Sie erinnern sich
‫daran, dass wir in diesem Schritt überprüfen, ob jemand die
‫Daten manipuliert hat oder auch, ob der Token bereits abgelaufen ist.
‫Wir haben also bereits aus dem JSON-Webtoken-Paket die Funktion zum
‫Zuweisen verwendet,
‫und jetzt verwenden wir die Verifizierungsfunktion.
‫Also genau wie zuvor, jwt. Verifizieren, und dann
‫übergeben wir dort, wie Sie sich vorstellen können, das Token, damit der
‫Algorithmus die Nutzlast lesen kann, und erinnern uns
‫dann daran, dass dieser Schritt auch das Geheimnis benötigt.
‫Also im Grunde, um die Testsignatur zu erstellen.
‫Dieses Geheimnis ist also der Prozess. env. JWT_SECRET.
‫Erinnere dich daran?
‫Als drittes
‫Argument erfordert diese Funktion nun tatsächlich eine Callback-Funktion.
‫Dieser Rückruf wird also
‫ausgeführt, sobald die Verifizierung abgeschlossen ist.
‫Sie sehen also, dass diese
‫Überprüfung hier eigentlich eine asynchrone Funktion ist.
‫Es wird also ein Token überprüfen und danach,
‫wenn es
‫fertig ist, die Callback-Funktion aufrufen, die wir angeben können.
‫Wir haben die ganze Zeit mit Versprechen
‫gearbeitet, und ich möchte dieses Muster hier nicht wirklich durchbrechen.
‫Und so werden wir diese Funktion tatsächlich versprechen.
‫Also im Grunde, um es zu einem Versprechen zurückzugeben.
‫Auf diese Weise können wir dann async-await
‫verwenden, genau wie jede andere async-Funktion, die wir verwendet haben.
‫Um dies zu
‫tun, verfügt Node tatsächlich über eine integrierte Versprechensfunktion.
‫Alles, was wir tun müssen, um
‫es zu verwenden, ist das eingebaute util-Modul.
‫Also lass uns das ganz oben machen.
‫Dadurch wird ein Objekt namens util erstellt, erfordern...
‫Alles klar, das steht also für Nützlichkeit.
‫Das war nicht das, was ich wollte.
‫Das steht also für Nutzwert.
‫Und dann werden wir die Versprechensmethode verwenden.
‫Aber da wir nur diese eine Methode verwenden werden, können
‫wir es tatsächlich einfacher machen.
‫Anstatt dies zu
‫tun, können wir dieses Objekt einfach destrukturieren und direkt
‫von dort aus Promisify nehmen.
‫Auch hier wird nur die ES6-Destrukturierung verwendet.
‫Okay, so und jetzt ist es sehr einfach zu bedienen.
‫Alles, was wir tun müssen, ist Versprechen zu nennen.
‫Versprechen Sie es also und übergeben Sie die Funktion dort.
‫All dies hier ist also eine Funktion, die
‫wir aufrufen
‫müssen, die dann ein Promise zurückgibt.
‫Also rufen wir hier die Funktion tatsächlich auf.
‫Und dies wird dann ein Promise
‫zurückgeben, und so können wir darauf warten und das Ergebnis in einer Variablen speichern.
‫Der Ergebniswert des Versprechens sind
‫also tatsächlich die
‫decodierten Daten, also die decodierten Nutzdaten dieses JSON-Webtokens.
‫Also lassen Sie es mich hier dekodiert nennen.
‫Gut.
‫Und wir können warten, weil wir bereits gesagt haben, dass es
‫sich um eine asynchrone Funktion handelt.
‫Und jetzt, nur um zu sehen, dass es tatsächlich
‫funktioniert, loggen wir diese entschlüsselten Daten auch in die Konsole ein.
‫Und tatsächlich können wir diese Konsole entfernen. das Token abmelden.
‫Den brauchen wir nicht mehr.
‫Versuchen wir also, diese Anfrage erneut zu senden, und ja,
‫aber diesmal schalten wir diesen Autorisierungsheader
‫tatsächlich ein, damit wir zusammen mit der Anfrage ein JSON-Webtoken senden.
‫Das hat es also geschickt.
‫Und nun bekommen wir tatsächlich Zugriff auf die
‫Daten und somit haben wir nun Zugriff auf den geschützten Weg.
‫Okay?
‫Aber was ich sehen wollte, ist dieses entschlüsselte Objekt hier.
‫Dies sollte hier also die Benutzer-ID sein.
‫Schauen wir uns das noch einmal in Postman an.
‫Also 62a42.
‫Und so, in der Tat, gut, wo haben wir das?
‫Werfen wir einen Blick auf Kompass.
‫Und tatsächlich ist die ID dieses Benutzers diese 62a42.
‫Und das bedeutet, dass wir hier
‫tatsächlich unsere richtige Nutzlast haben.
‫Also im Grunde die richtige Benutzer-ID.
‫Wir haben dann auch den Zeitstempel des
‫Erstellungsdatums und des Ablaufdatums des Tokens.
‫Das funktioniert also.
‫Aber jetzt versuchen wir tatsächlich, die Nutzlast dieses Tokens
‫zu manipulieren.
‫Also kopieren wir es hier noch einmal.
‫Aber dann gehe ich zum JWT-Debugger.
‫Also nochmal bei jwt. io.
‫Nehmen wir das also weg.
‫Und jetzt werde ich hier einige Daten ändern,
‫und das ändert dann den codierten Token hier, den
‫ich dann kopieren kann.
‫Also lasst uns einfach ersetzen,
‫eigentlich werde ich diese beiden Zahlen hier einfach
‫durch etwas anderes ersetzen.
‫Und wie Sie sehen, hat dies hier den Token geändert.
‫Und jetzt werde ich tatsächlich versuchen,
‫mit diesem manipulierten
‫JSON-Webtoken Zugriff auf diese geschützte Route zu erhalten.
‫Okay, sinnvoll?
‫Also nur um zu sehen, ob es richtig funktioniert.
‫Also kopiere ich
‫jetzt diesen hier und füge diesen anderen anderen ein.
‫Also, wenn ich jetzt diese Anfrage sende, dann bekommen wir einen Fehler.
‫So großartig.
‫Wir sehen also, dass der Fehlername JsonWebTokenError ist
‫und wir eine ungültige Signatur haben.
‫So großartig.
‫Genau das haben wir gesucht.
‫Das ist also einer der beiden Fehler, die auftreten können.
‫Der andere ist, dass der Token bereits abgelaufen ist.
‫Dieser heißt also JsonWebTokenError, und
‫lassen Sie uns diesen Fehler jetzt behandeln.
‫Und wir
‫könnten dies tun, indem wir hier einen Try-Catch-Block hinzufügen.
‫Richtig?
‫Also könnten wir direkt nach der
‫Ausführung dieses Codes einen
‫try-Block einführen und dann im Catch Fehler erzeugen,
‫die an den Client gesendet werden.
‫Anstatt es so zu machen,
‫möchte ich jetzt eigentlich unsere globale Middleware zur Fehlerbehandlung
‫verwenden, um das für uns zu tun.
‫Daher möchten wir die Fehlerbehandlung nicht gleich hier
‫in unserer Middleware-Funktion durchführen.
‫Stattdessen delegieren wir es normalerweise an den Fehlercontroller.
‫Und so machen wir hier genau das Gleiche.
‫Also Fehlercontroller.
‫Und dann ist es eigentlich
‫genau dasselbe wie bei unseren anderen Fehlern hier.
‫So kommt zum Beispiel der Validierungsfehler von Mongoose, also
‫von einer anderen Bibliothek.
‫Und jetzt kommt dieser Fehler tatsächlich von einer anderen
‫Bibliothek und hat auch einen eigenen Namen.
‫Also lass uns das bekommen.
‫Und es ist JsonWebTokenError.
‫Gut.
‫Also, lassen Sie uns hier ganz ähnlich vorgehen.
‫Also wenn. name
‫ist dies, dann sollte error gleich handle error sein.
‫Okay.
‫Lassen Sie uns
‫also weitermachen und diese Funktion tatsächlich irgendwo hier oben erstellen.
‫Und dieser ist eigentlich ganz einfach.
‫Alles, was es tut, ist, einen Fehler zu
‫akzeptieren und dann einen neuen AppError zurückzugeben.
‫Okay?
‫In dieser
‫ES6-Pfeilfunktion können wir, wie Sie hoffentlich wissen, diese Einzeiler schreiben, bei
‫denen wir nicht einmal die
‫geschweiften Klammern und auch das Schlüsselwort return angeben müssen.
‫Dies wird also automatisch
‫und implizit alles zurückgeben, was wir hier eingeben.
‫Richtig?
‫Was wir
‫hier also einfach sagen möchten, ist ungültiges Token, bitte loggen
‫Sie sich erneut ein.
‫Und dann ist der Fehlercode wie zuvor
‫ein 401 für Unauthorized.
‫Nun, das funktioniert nur in der Produktion, denken Sie daran.
‫Und wenn wir das jetzt noch einmal machen
‫würden, würden wir genau dasselbe bekommen.
‫Lassen Sie uns also tatsächlich hierher zurückkehren und
‫dies in der Produktion ausführen.
‫Also npm run start:production.
‫Ja, einfach so.
‫Wenn wir dies jetzt noch
‫einmal versuchen, sehen wir, ob wir unseren Fehler erhalten.
‫Und das tun wir tatsächlich.
‫Wenn also gerade ein Benutzer in der
‫Produktion versucht, mit einem ungültigen Token
‫auf unsere App zuzugreifen, erhält er nur diese Fehlermeldung.
‫Gut?
‫Das ist also der erste Fehler, den wir bekommen können.
‫Ein anderer ist jedoch, dass der Benutzer versucht,
‫mit einem bereits abgelaufenen
‫Token auf die Anwendung zuzugreifen.
‫Versuchen wir nun, diesen Fehler zu erstellen.
‫Und um dies zu tun, werde
‫ich die Zeit bis zum Ablauf des Tokens ändern.
‫Im Moment haben wir also 90 Tage Zeit.
‫Sagen wir mal fünf Sekunden.
‫Okay.
‫Sparen Sie.
‫Und jetzt versuchen Sie sich erneut anzumelden.
‫Also lasst uns das hier auch tatsächlich speichern.
‫Also, in Benutzer und dann einloggen.
‫Wir können uns also einloggen und erhalten dann einen neuen
‫Token, der jedoch nur fünf Sekunden gültig ist.
‫Und so sollten diese fünf Sekunden zu diesem Zeitpunkt verstrichen sein.
‫Also werde ich jetzt dieses Token kopieren und versuchen, mit diesem
‫Token auf unsere geschützte Route zuzugreifen.
‫Also füge es hier ein.
‫Und jetzt wollen wir sehen, was wir bekommen.
‫Und tatsächlich hat es aus irgendeinem Grund funktioniert.
‫Werfen wir also noch einmal einen Blick auf unseren JWT-Debugger.
‫Und es heißt, erstellt am 2. Mai, läuft aber
‫erst am 31. Juli ab.
‫Also ist bei dieser Token-Erstellung etwas schief gelaufen, denke ich.
‫Also ändern wir das hier noch einmal.
‫Und ich werde nur fünf hier setzen.
‫Und so, dass fünf dann für
‫fünf Millisekunden stehen sollte, oder ich kann sogar 5000
‫sagen, was dann fünf Sekunden sein sollten.
‫Okay.
‫Lassen Sie mich es jetzt noch einmal speichern, um den Server neu zu starten.
‫Versuchen Sie es erneut.
‫Melden Sie sich also hier erneut an.
‫Gut.
‫Jetzt müssen wir
‫also nur noch fünf Sekunden warten, und diese Zeit sollte zu diesem Zeitpunkt bereits vergangen sein.
‫Fügen Sie es hier wieder ein.
‫Und los geht's.
‫Und tatsächlich erhalten wir einen Fehler.
‫Denken Sie jetzt daran, dass
‫dies im Grunde der Standardfehler ist, den wir erhalten, falls
‫wir diesen Fehler in unserer Fehlerbehandlung nicht richtig behandeln.
‫Richtig?
‫Schauen wir uns also den Fehler einmal an.
‫Und tatsächlich haben wir es hier in der Konsole.
‫Mal sehen, woher das kommt.
‫Und ja, es kommt von diesem Ort.
‫Dies ist also der Fall, wenn wir einen unbekannten Fehler haben.
‫Denken Sie daran, dass ein Fehler, der nicht
‫als Betriebsfehler gekennzeichnet ist, daher
‫protokolliert wird.
‫Also loggen wir es hier ein und
‫senden dann diese generische Fehlermeldung
‫an den Client, also die, die wir gerade in
‫Postman gesehen haben.
‫Aber hier haben wir eigentlich die Details zu diesem Fehler.
‫Dieser hat den Namen TokenExpiredError.
‫Gut.
‫Also lassen Sie uns jetzt auch mit diesem umgehen.
‫Also kopiere ich es jetzt und erstelle dann einfach
‫ein anderes, wenn hier.
‫Also wenn der Fehler. name ist gleich diesem, also nehmen wir
‫an, behandeln Sie JWTExpiredError
‫mit
‫dem Pfeil.
‫Lass es uns kopieren und gleich hier ablegen.
‫Und so ist dies natürlich dem vorherigen sehr ähnlich.
‫Ihr Token ist abgelaufen.
‫Bitte melden Sie sich erneut an.
‫Und wieder mit einem 401 Fehlercode.
‫Okay, versuchen wir es noch einmal.
‫Und genau das ist die Fehlermeldung, die
‫wir jetzt hier sehen sollten.
‫Gut.
‫Und tatsächlich ist es so.
‫Toll.
‫Lassen Sie uns den
‫Vorgang hier beenden und natürlich im Dev-Modus starten.
‫Also npm
‫starten und in Ordnung.
‫Also dieses hier brauchen wir nicht mehr, also schließen wir es.
‫Oder lassen Sie uns diesen kleinen Fehler hier beheben, denn tatsächlich
‫verwenden wir diesen Fehler hier überhaupt nicht.
‫Also lass es uns loswerden.
‫Und dann hier unten, wir brauchen es dort nicht weiterzugeben.
‫Cool.
‫Wir müssen dies natürlich auch wieder auf 90 Tage ändern.
‫Gut.
‫Um ganz
‫sicher zu gehen, loggen wir uns also noch einmal hier ein,
‫kopieren den Token
‫und legen ihn hier ab.
‫Nun, dieser Vorgang hier, den Token zu
‫kopieren und dann hier in diesen Header einzufügen,
‫mag etwas seltsam erscheinen, und wir werden das
‫in einem der
‫zukünftigen Videos beheben, sodass dieser
‫Vorgang im Grunde automatisch abläuft.
‫Aber jetzt ist es wichtig, dass es
‫jetzt tatsächlich wieder funktioniert.
‫Wir können diese Konsole also tatsächlich loswerden. Melden Sie sich hier an und fahren Sie
‫mit dem nächsten Schritt fort.
‫Und wir könnten jetzt tatsächlich hier aufhören, wenn wir wollten.
‫Und wieder würden die meisten Tutorials,
‫die Sie dort finden werden, tatsächlich hier aufhören.
‫Aber das ist noch nicht wirklich sicher genug.
‫Was ist also beispielsweise, wenn der
‫Benutzer zwischenzeitlich gelöscht wurde?
‫Das Token wird also noch existieren, aber wenn
‫der Benutzer nicht mehr existiert, dann
‫wollen wir ihn eigentlich nicht einloggen, oder?
‫Oder noch schlimmer, was ist, wenn der Benutzer sein
‫Passwort nach der Ausgabe des
‫Tokens tatsächlich geändert hat?
‫Nun, das sollte auch nicht funktionieren, oder?
‫Stellen Sie sich beispielsweise vor,
‫dass jemand das JSON-Webtoken von einem Benutzer gestohlen hat.
‫Um sich davor
‫zu schützen, ändert der Benutzer dann aber sein Passwort.
‫Und so sollte natürlich das alte Token, das
‫vor der Passwortänderung ausgestellt wurde, nicht mehr gültig sein.
‫Es sollte daher nicht akzeptiert werden, auf geschützte Routen zuzugreifen.
‫Und das ist die Art von Sachen, die wir hier in
‫Schritt drei und Schritt vier implementieren werden.
‫Als erstes ist also zu prüfen, ob der Benutzer
‫tatsächlich noch existiert.
‫Und so sollte das am einfachsten sein.
‫Sagen wir einfach Benutzer. findById.
‫Aus diesem Grund haben wir die ID
‫jetzt tatsächlich in der Nutzlast,
‫weil wir jetzt diese ID verwenden und
‫den Benutzer nur mit dieser ID abfragen können.
‫Also entschlüsselt. Ich würde.
‫Gut?
‫Damit sollte dann der neue Benutzer gefunden werden.
‫Und natürlich müssen wir das abwarten und
‫dann in einer Variablen speichern.
‫Ich nenne es den freshUser.
‫Gut?
‫Weil es nicht wirklich ein neuer Benutzer ist.
‫Das ist nur, wenn wir eine erstellen.
‫Aber das ist nicht wirklich neu, es ist wirklich
‫nur der Benutzer anhand der entschlüsselten ID.
‫Okay?
‫Und wir
‫können dies tun, um 100% sicher zu sein, dass die
‫ID tatsächlich korrekt ist, denn wenn wir es
‫bis zu diesem Punkt des Codes hier geschafft haben, bedeutet dies, dass der
‫Überprüfungsprozess, den wir zuvor hier durchgeführt haben, erfolgreich war.
‫Andernfalls hätte dies einen Fehler verursacht, der
‫die Fortsetzung der Funktion
‫verhindert hätte.
‫Auch hier ist dieser
‫Überprüfungsprozess für die Überprüfung verantwortlich, wenn niemand die
‫ID geändert hat, die sich
‫in der Nutzlast dieses Tokens befindet.
‫Aus diesem Grund können wir
‫100% sicher sein, dass der Benutzer, für den wir
‫das JWT ausgestellt haben, genau derjenige ist, dessen ID jetzt in
‫der decodierten Nutzlast enthalten ist, also dieser.
‫Okay?
‫Der Verifizierungsprozess ist also wirklich der Schlüssel.
‫Es ist wirklich das, was all dies funktioniert.
‫Wie auch immer, jetzt müssen wir überprüfen, ob
‫es tatsächlich einen freshUser gibt.
‫Und wenn nicht, dann geben wir natürlich
‫einen neuen Fehler zurück.
‫Wenn also kein freshUser vorhanden ist, kehren
‫Sie von dieser Middleware zurück und rufen Sie
‫die nächste mit einem Fehler auf.
‫Dies ist also ein Muster, das
‫wir an dieser Stelle immer wieder sehen, oder?
‫Der Token existiert also nicht
‫mehr.
‫Und eigentlich ist es umgekehrt.
‫Der zum Token gehörende
‫Benutzer existiert also tatsächlich nicht mehr.
‫Richtig?
‫Und dann die 401.
‫Okay.
‫Lassen Sie uns das also noch einmal testen.
‫Und lassen Sie uns dafür tatsächlich einen neuen Benutzer erstellen.
‫Testen Sie also einfach mit demselben Passwort, damit wir hier
‫immer das gleiche Passwort verwenden, nur um unser
‫Testen etwas einfacher zu machen.
‫Und ich weiß, dass all diese Tests hier das
‫Video ziemlich lange dauern lassen, aber
‫natürlich ist es wirklich wichtig, dass wir alles testen, was wir
‫tun, insbesondere bei
‫einem so wichtigen Thema wie der Authentifizierung.
‫Also verwende ich jetzt dieses JWT hier, also füge
‫ich es hier ein, aber vor dem Senden der Anfrage werde
‫ich diesen Benutzer natürlich sofort löschen.
‫Okay?
‫Nehmen wir also noch einmal
‫an, dass jemand einen Benutzer erstellt und sich dann angemeldet
‫hat, und nehmen wir an, der Benutzer wurde nach einiger Zeit gelöscht.
‫Aber in der Zwischenzeit könnte jemand Zugang zu diesem
‫JWT
‫erhalten und nun versuchen, sich als dieser Benutzer
‫anzumelden, der tatsächlich bereits gelöscht wurde.
‫Und so sollten wir das wiederum nicht zulassen.
‫Lassen Sie mich diesen Benutzer jetzt hier löschen.
‫Und los gehts.
‫Und so testen wir es jetzt.
‫Denken Sie auch hier daran, dass der Benutzer,
‫der zu der ID gehört, die sich in dieser Nutzlast befindet, jetzt nicht mehr vorhanden ist.
‫Also mal sehen.
‫Und tatsächlich erhalten wir diese Fehlermeldung, die wir gerade erstellt haben.
‫Damit funktioniert es auch.
‫Und gehen wir zum letzten.
‫Schritt Nummer vier, überprüfen Sie, ob der Benutzer
‫kürzlich sein Passwort geändert hat.
‫Also im Grunde nach der Ausgabe des Tokens.
‫Und um diesen Test zu implementieren, werden wir tatsächlich
‫eine weitere Instanzmethode erstellen.
‫Im Grunde also eine Methode,
‫die für alle Dokumente verfügbar sein wird.
‫Dokumente sind also Instanzen eines Modells.
‫Gut?
‫Und wir tun
‫dies, weil wir für diese Überprüfung ziemlich viel Code benötigen.
‫Dieser Code gehört also
‫eigentlich zum Benutzermodell und nicht wirklich zum Controller.
‫Okay?
‫Machen wir das also
‫genau so, wie wir es zuvor bei der Überprüfung des Passworts getan haben.
‫Im Benutzermodell haben wir diese statische
‫Instanzmethode korrektPassword bereits implementiert, erinnern Sie sich?
‫Und so erstellen wir jetzt einen weiteren.
‫Also userSchema. Methoden. geändertPasswortNach.
‫Funktionieren Sie also, und
‫in diese Funktion übergeben wir den JWT-Zeitstempel.
‫Im Grunde also der Zeitstempel, der angibt, wann
‫das Token ausgestellt wurde.
‫Nennen wir das also JWTTimestamp.
‫Gut.
‫Und standardmäßig geben wir von dieser Methode false zurück.
‫Und das bedeutet dann, dass der Benutzer sein Passwort
‫nach der
‫Ausgabe des Tokens nicht geändert hat.
‫Okay?
‫Lassen Sie uns das hier setzen, geben wir im Grunde standardmäßig false zurück.
‫Okay.
‫Aber dann
‫haben wir auch if this, und denken Sie daran, dass in einer Instanzmethode
‫das Schlüsselwort this immer auf das aktuelle Dokument zeigt.
‫Und so haben wir hier also Zugriff auf die Eigenschaften.
‫Nun müssen wir tatsächlich in unserem Schema ein Feld für das
‫Datum erstellen, an dem das Passwort geändert wurde.
‫Das haben wir also noch nicht.
‫Also fügen wir es hier schnell hinzu.
‫Also passwordChangedAt, und der Typ davon
‫ist ein Datum.
‫Nun wird diese Eigenschaft passwordChangedAt
‫hier natürlich immer geändert, wenn jemand
‫das Passwort ändert.
‫Im Moment haben wir diese Logik nirgendwo, und
‫daher definieren wir diese Eigenschaft nirgendwo.
‫Und so haben die meisten Dokumente,
‫also die meisten Benutzer, diese Eigenschaft einfach nicht
‫in ihren Daten, also in ihrem Objekt, oder?
‫Und das müssen wir natürlich testen.
‫Okay?
‫Wenn also die
‫Eigenschaft passwordChangedAt vorhanden ist, möchten wir den Vergleich nur dann durchführen.
‫Okay?
‫Aber wenn
‫nicht, also wenn passwordChanged nicht existiert, bedeutet dies, dass der Benutzer das
‫Passwort nie wirklich geändert hat,
‫und daher können wir einfach false zurückgeben.
‫Dies ist also wieder unsere Standardeinstellung, was bedeutet,
‫dass der Benutzer das Passwort
‫nach diesem Zeitstempel nicht geändert hat.
‫Okay.
‫Und jetzt,
‫nur um zu beginnen, lassen Sie uns dies tatsächlich in die Konsole einloggen. passwordChangedAt und natürlich auch der JWTTimestamp, nur damit wir
‫sehen können,
‫wie wir sie vergleichen können.
‫Gut.
‫Und jetzt müssen
‫wir tatsächlich einen Benutzer erstellen, der diese Eigenschaft hat, okay?
‫Und später in dem Abschnitt, in dem wir die
‫Logik zum Ändern des
‫Passworts implementieren, werden wir dann diese Eigenschaft festlegen.
‫Okay?
‫Aber jetzt werden
‫wir es im Grunde künstlich hier setzen, wenn wir einen neuen Benutzer erstellen.
‫Okay?
‫Stellen wir das also hier.
‫Und hier wird jedes Datum tatsächlich dienen.
‫Sagen wir also den 30. April 2019 hier.
‫Und das sollte dann problemlos in MongoDB geparst werden.
‫Lassen Sie uns das versuchen, sehen, ob es funktioniert.
‫Und das hat nicht funktioniert.
‫Sagen wir, es konnte das Datum nicht wirklich analysieren.
‫Und eigentlich muss ich mit dem Jahr beginnen und
‫dann mit dem Tag am Ende.
‫Also 2019 und dann 30. April.
‫Versuchen Sie das noch einmal.
‫Und Sie sehen, dass es jetzt tatsächlich funktioniert.
‫Wir haben also dieses geparste Datum hier.
‫Okay?
‫Um das Ergebnis
‫tatsächlich zu sehen, müssen wir diese Methode natürlich aufrufen.
‫Okay?
‫Das machen wir hier in Schritt vier.
‫Okay?
‫Denken Sie also
‫daran, dass wir diese Instanzmethode für ein Benutzerdokument aufrufen können.
‫Also freshUser. changePasswordAfter und dann
‫dieser Zeitstempel.
‫Das ist also bei dekodiert. iat, also im Grunde ausgestellt.
‫Gut.
‫Sehen wir uns also einfach das Ergebnis davon an.
‫Und so sollte dies jetzt natürlich nicht hier
‫sein, also sollte dies nun diese beiden Werte in die Konsole einloggen.
‫Okay.
‫Jetzt muss
‫ich mich natürlich mit genau diesem Benutzer einloggen, also mit
‫Test, also los geht's.
‫Einloggen.
‫Kopieren Sie dieses Token erneut hierher.
‫Und wieder werden wir das
‫im nächsten Video im Grunde automatisieren.
‫Okay.
‫Fügen Sie es hier ein.
‫Und jetzt bekommen wir diesen Fehler hier tatsächlich.
‫Also habe ich diesen Funktionsnamen hier einfach falsch geschrieben.
‫Nun, kopieren wir es einfach.
‫Versuchen Sie es erneut.
‫Oh Mann.
‫Was läuft jetzt schief?
‫Und wie ich sehe, habe ich dieses Protokoll hier einfach vergessen.
‫Also noch ein blöder Fehler.
‫Habe das wahrscheinlich kommen sehen.
‫Aber jetzt geht es los.
‫Es hat also
‫alles gut geklappt und alles, was
‫wir jetzt wirklich sehen wollten, sind diese beiden Ergebnisse.
‫Wir haben also im Grunde dieses eine
‫hier dieses Datumsformat und dann das andere in diesem Millisekunden- oder zweiten
‫Zeitstempel hier.
‫Also müssen wir dieses passwordChangedAt
‫jetzt auch in einen solchen Zeitstempel konvertieren.
‫Gut?
‫Lassen Sie uns dafür eine neue Variable erstellen.
‫Also geänderter Zeitstempel.
‫Und das können wir gebrauchen. passwordChangedAt. Zeit kriegen.
‫Okay?
‫Das ist
‫also eine der vielen, vielen Datumsfunktionen, die uns JavaScript bietet.
‫Gut.
‫Und jetzt lassen Sie uns
‫diese beiden schnell vergleichen, denn wir sind noch nicht ganz fertig.
‫Senden Sie es einfach, um die Ergebnisse hier zu sehen.
‫Was wir hier also im Grunde sehen, ist, dass
‫dieser hier jetzt im
‫Grunde in Sekunden ist und dieser in Millisekunden.
‫Also 1000 mal mehr.
‫Wir wissen also, dass wir dies durch 1000
‫teilen und dann das Ganze als ganze Zahl analysieren müssen.
‫Und dafür verwenden wir parseInt.
‫Also eine weitere JavaScript-Funktion, die für Zahlen verfügbar ist.
‫Und dann müssen wir eigentlich auch noch die Basis angeben.
‫Dies ist also eine Zahl zur Basis 10.
‫Gut?
‫Und nun sehen wir uns das Ergebnis noch einmal genauer an.
‫Und das sieht jetzt viel freundlicher aus.
‫Okay.
‫Lassen Sie uns nun unser Ergebnis zurückgeben.
‫Und denken Sie noch einmal daran, dass falsch bedeutet, dass sich nichts geändert hat.
‫Okay?
‫Und nicht geändert
‫bedeutet im Grunde, dass der Tag oder die Uhrzeit, zu der der Token ausgestellt wurde,
‫kleiner ist als der geänderte Zeitstempel.
‫Okay?
‫Nehmen wir hier nur als
‫Beispiel an, dass der Token zum Zeitpunkt 100 ausgestellt wurde.
‫Aber dann haben wir das Passwort geändert, sagen wir zum Zeitpunkt 200.
‫Okay?
‫Daher haben
‫wir das Passwort nach der Ausgabe
‫des Tokens geändert, und daher ist dies jetzt wahr.
‫Gut?
‫Und genau das wollen wir
‫hier zurückgeben, denn falsch
‫bedeutet nicht geändert, und wahr bedeutet natürlich geändert.
‫Und genau das haben wir hier.
‫Aber jetzt, sagen wir, das Passwort wurde zuletzt
‫um 200 geändert,
‫aber erst danach haben wir das
‫Token ausgegeben, also sagen wir zum Zeitpunkt 300.
‫Also 300, weniger als 200?
‫Nein, das ist falsch.
‫Und so geben wir false zurück, was wiederum nicht geändert bedeutet.
‫Deshalb verwenden wir hier dieses weniger Zeichen.
‫Okay?
‫Kehren wir zu unserem Controller zurück und verwenden diesen tatsächlich.
‫Wenn also das Passwort tatsächlich geändert wurde, nun, in
‫diesem Fall wollen wir eigentlich einen Fehler.
‫Geben Sie also als nächstes wieder einen neuen AppError zurück.
‫Vor kurzem...
‫Bitte melden Sie sich erneut an.
‫Okay.
‫Und noch einmal Code 401.
‫Gut.
‫Auch hier wird
‫true zurückgegeben, wenn der Benutzer sein Passwort tatsächlich geändert hat.
‫Also, wenn all dies hier wahr ist,
‫nun, dann wollen wir genau in diesem Fall,
‫dass dieser Fehler passiert.
‫Gut?
‫Das war also eigentlich der letzte Schritt.
‫Okay.
‫Also im Grunde, wenn der Code hier alles
‫bis zum Ende dieses Codes schafft, wird nur dann der nächste ausgeführt.
‫Und dann gehen wir mit next zum nächsten Route-Handler,
‫was effektiv bedeutet, den Zugriff auf diese
‫geschützte Route zu gewähren.
‫Lassen Sie uns das hier wirklich setzen.
‫Gewähren Sie Zugriff auf die geschützte Route.
‫Okay?
‫Denn das ist wirklich alles, was das nächste tut.
‫Weiter führt uns zur
‫nächsten Middleware, die dann normalerweise der Route-Handler selbst
‫ist, also diejenige, die die geschützten Daten zurücksendet.
‫Okay.
‫Nur als
‫letztes wollen wir hier tatsächlich die gesamten Nutzerdaten auf die Anfrage stellen.
‫Wir können also einfach sagen, req, also bitte, . user wird dem freshUser gleich
‫sein.
‫Okay.
‫Und auch
‫hier erreicht der Code
‫natürlich immer nur diesen Punkt, wenn alles stimmt.
‫Okay?
‫Und so könnte
‫dies hier vielleicht irgendwann in der Zukunft nützlich sein.
‫Toll.
‫Lass uns das einfach noch einmal testen.
‫Und im Grunde ist diese Veränderung jetzt Vergangenheit.
‫Also dieses Token, das wir hier haben, oder eigentlich hätte
‫ich nur dieses
‫wiederverwenden können, anstatt es erneut zu protokollieren.
‫Aber egal, dieses Token
‫wurde ausgegeben, nachdem das Passwort geändert wurde.
‫Dieses Token sollte nun funktionieren.
‫Loggen wir uns also noch einmal
‫ein und versuchen es mit diesem Token.
‫Und tatsächlich bekommen wir Zugang.
‫Wechseln Sie nun zu Compass, um dieses Datum zu ändern.
‫Okay.
‫Sagen wir einen Monat später.
‫Und das wird tatsächlich in Zukunft
‫so sein, also zumindest in meiner Zukunft, wenn ich dieses Video aufnehme.
‫Natürlich werden Sie dies zu einem späteren Zeitpunkt tun.
‫Um dies zu testen, legen Sie dies bitte in Ihre Zukunft.
‫Also in der Zukunft des Datums, an dem Sie
‫dieses Video ansehen.
‫Also wenn ich jetzt
‫zurück zu Postman gehe und mich wieder einlogge, okay, also wenn ich mich jetzt
‫wieder einlogge und versuche, auf diese Route
‫zuzugreifen, nun, dann wird dieser Token
‫im Grunde nach der Änderung des Passworts ausgestellt.
‫Oder tatsächlich bevor das Passwort geändert wurde.
‫Also sorry für diese Verwirrung.
‫Das Passwort wurde also am 30. Mai
‫geändert, aber dieses Token wurde am 2. Mai ausgestellt und so zuvor.
‫Im Grunde ist es jetzt so, als ob der Benutzer sein Passwort
‫nach der Ausgabe des Tokens geändert hätte.
‫Und genau das ist die Situation, in der wir den Zugang zum geschützten
‫Weg nicht gewähren wollen.
‫Und so sollte dies nun auch das widerspiegeln.
‫Und tatsächlich, der Benutzer hat kürzlich das Passwort geändert,
‫bitte melden Sie sich erneut an.
‫Toll.
‫Also das funktioniert jetzt.
‫Damit ist unsere Protect Middleware nun vollständig implementiert.
‫Lassen Sie uns diese Konsole einfach loswerden. hier einloggen.
‫Brauche das nicht mehr.
‫Und okay.
‫Fassen wir also kurz zusammen, und
‫dieses Video dauert sehr
‫lange, etwas länger als ich erwartet hatte.
‫Aber es ist wirklich
‫wichtig zu verstehen und zu erklären, wie
‫das alles funktioniert und warum es wichtig ist.
‫Und deshalb bevorzuge ich das, als dieses Video viel kürzer zu machen.
‫Natürlich könnte ich einfach den Code schreiben, aber dann würdest du nicht wirklich verstehen,
‫was los ist.
‫Diesen Teil haben wir also bereits verstanden.
‫Dann, glaube ich, auch dieser Teil,
‫hier findet also die Verifizierung statt, also
‫im Grunde genommen, um zu sehen, ob die
‫Token-Nutzlast nicht von einem böswilligen Dritten manipuliert wurde.
‫Okay?
‫Und da wir
‫diesen Code dann hier erreichen, bedeutet dies, dass
‫niemand den JSON-Webtoken geändert hat und wir daher einen neuen Benutzer bekommen können.
‫Im Grunde können wir also den aktuellen Benutzer
‫abrufen, nennen wir ihn eigentlich currentUser.
‫Warum nicht?
‫Also hier, hier und auch hier.
‫Okay?
‫So können wir
‫den aktuellenBenutzer von dieser ID abrufen, die gerade aus der Nutzlast entschlüsselt wurde.
‫Wenn der currentUser nicht vorhanden
‫ist, testen wir hier darauf, nun,
‫in diesem Fall möchten wir keinen Zugriff
‫auf die Route
‫gewähren und stattdessen diesen neuen Fehler erstellen.
‫Aber wenn der Benutzer existiert, gut,
‫dann schaffen wir es
‫zu Punkt Nummer vier, wo wir dann überprüfen, ob nach
‫der Ausgabe des Tokens eine Passwortänderung stattgefunden hat, oder?
‫Und wenn dies der Fall ist, erstellen wir erneut einen neuen Fehler.
‫Und wenn nicht, gut, dann schaffen wir es
‫bis zum Ende
‫der Middleware-Funktion, wo wir
‫dann den currentUser zum Request zuweisen. user, damit wir es dann in
‫einer nächsten Middleware-Funktion verwenden können.
‫Okay?
‫Denken Sie
‫daran, dass dieses Anforderungsobjekt im Grunde
‫von Middleware zu Middleware wandert.
‫Wenn wir also Daten von einer
‫Middleware zur nächsten weitergeben
‫möchten, können wir einfach etwas auf das Anforderungsobjekt
‫legen, und diese Daten stehen zu einem späteren Zeitpunkt zur Verfügung.
‫Gut.
‫So, das wars.
‫Dies ist
‫im Grunde ein sehr ausgeklügelter und
‫sehr vollständiger Routenschutzalgorithmus, aber ich denke, es ist wirklich wichtig, ihn so gut
‫wie möglich zu machen.
‫Wie auch immer, ich freue mich zu sehen, dass du es
‫bis zum Ende dieses großen Videos geschafft hast,
‫und wir sehen uns im nächsten.