Grundlegendes zum Pass Serialize Deserialize

337

Wie würden Sie einem Laien den Workflow der Serialisierungs- und Deserialisierungsmethoden von Passport erklären?

  1. Wohin geht das user.id, nachdem passport.serializeUseres gerufen wurde?

  2. Wir rufen passport.deserializeUsergleich danach an, wo passt es in den Workflow?

    // used to serialize the user for the session
    passport.serializeUser(function(user, done) {
        done(null, user.id); 
       // where is this user.id going? Are we supposed to access this anywhere?
    });
    
    // used to deserialize the user
    passport.deserializeUser(function(id, done) {
        User.findById(id, function(err, user) {
            done(err, user);
        });
    });

Ich versuche immer noch, meinen Kopf darum zu wickeln. Ich habe eine vollständig funktionierende App und stoße auf keinerlei Fehler.

Ich wollte nur verstehen, was genau hier passiert?

Jede Hilfe wird geschätzt.

Anubhav
quelle

Antworten:

451
  1. Wohin geht das user.id, nachdem passport.serializeUseres gerufen wurde?

Die Benutzer-ID (die Sie als zweites Argument der doneFunktion angeben) wird in der Sitzung gespeichert und später zum Abrufen des gesamten Objekts über die deserializeUserFunktion verwendet.

serializeUserlegt fest, welche Daten des Benutzerobjekts in der Sitzung gespeichert werden sollen. Das Ergebnis der serializeUser-Methode wird an die Sitzung als angehängt req.session.passport.user = {}. Hier wäre es zum Beispiel (da wir die Benutzer-ID als Schlüssel angeben)req.session.passport.user = {id: 'xyz'}

  1. Wir rufen passport.deserializeUsergleich danach an, wo passt es in den Workflow?

Das erste Argument von deserializeUserentspricht dem Schlüssel des Benutzerobjekts, das der doneFunktion übergeben wurde (siehe 1.). Mit diesem Schlüssel wird also Ihr gesamtes Objekt abgerufen. Dieser Schlüssel ist hier die Benutzer-ID (Schlüssel kann ein beliebiger Schlüssel des Benutzerobjekts sein, z. B. Name, E-Mail usw.). ImdeserializeUser diesem Schlüssel wird mit dem In-Memory-Array / der Datenbank oder einer beliebigen Datenressource abgeglichen.

Das abgerufene Objekt wird als an das Anforderungsobjekt angehängt req.user

Visueller Fluss

passport.serializeUser(function(user, done) {
    done(null, user.id);
});              
                  
                 
                 └─────────────────┬──→ saved to session
                                       req.session.passport.user = {id: '..'}
                                   
                                              
passport.deserializeUser(function(id, done) {
                   ┌───────────────┘
                   
                    
    User.findById(id, function(err, user) {
        done(err, user);
    });            └──────────────→ user object attaches to the request as req.user   
});
AB
quelle
2
So wird user.idgespeichert als req.session.passport.useroder userselbst gespeichert alsreq.session.passport.user
Anubhav
@AB Ich habe Code geschrieben, um den Benutzer anhand der ID zu finden, die übergeben wurde, um die Methode als ersten Parameter zu deserialisieren. Bei jeder Anforderung wird jedoch ein Benutzer aus der Datenbank abgerufen. Dies führt zu einem Leistungsverlust für db. Was sollte ich noch schreiben, um die Funktion zu deserialisieren und zu überprüfen, ob sie in der Sitzung vorhanden ist oder nicht?
uzay95
2
@AB Ich verstehe nicht, was Sie uzay95 vorgeschlagen haben. In meiner Sitzung habe ich also nur user._id. Aber bei jeder Anfrage muss ich diese ID verwenden, um sie aus der Datenbank aka findUserByID zu deserialisieren, und das wird sie in req.user ablegen. Wie vermeide ich es, bei jeder Anfrage einen solchen Anruf zu tätigen?
Zanko
10
@Zanko Sie könnten das gesamte Benutzerobjekt in die Sitzungsdaten einfügen, aber das ist normalerweise keine gute Idee, da es andere Nebenwirkungen haben kann. Wenn der Benutzer beispielsweise seinen Benutzernamen aktualisiert, müssen Sie auch die Sitzungsdaten aktualisieren. Andernfalls erhalten Sie Tickets aufgrund der "defekten Umbenennungsfunktion". Das ist ein relativ harmloses Beispiel. Gleiches kann mit Berechtigungsbits oder gleich sensiblen Daten geschehen (Ups ...). Im Wesentlichen dieselben Probleme, auf die Sie immer stoßen, wenn Sie doppelte Daten haben. TL; DR - Tu es nicht.
Max Truxa
1
Wenn ich mich nicht irre, ist der req.session.passport.user = {id: '..'}Teil des Diagramms leicht abweichend und sollte req.session.passport.user = 785352stattdessen sein, wo 785352ist user.id. Ich habe Probleme mit der Konsolenprotokollierung, um dies zu beweisen, aber es scheint sinnvoll zu sein. Wenn Sie anrufen done(null, user.id);, ist es sinnvoll, das zweite Argument - user.idin diesem Fall - zu verwenden req.session.passport.user, anstatt es zuzuweisen req.session.passport.user.id. Denn was ist, wenn Sie stattdessen vorbeikommen user? req.sesssion.passport.user.id = userwürde keinen Sinn ergeben.
Adam Zerner
21

Für alle, die Koa und Koa-Pass verwenden :

Beachten Sie, dass der in der serializeUser-Methode festgelegte Schlüssel für den Benutzer (häufig eine eindeutige ID für diesen Benutzer) gespeichert wird in:

this.session.passport.user

Wenn Sie done(null, user)in deserializeUser festlegen, dass 'user' ein Benutzerobjekt aus Ihrer Datenbank ist:

this.req.user ODER this.passport.user

aus irgendeinem Grund this.user Koa-Kontext nie festgelegt, wenn Sie in Ihrer deserializeUser-Methode done (null, user) aufrufen.

Sie können also nach dem Aufruf von app.use (passport.session ()) Ihre eigene Middleware schreiben, um sie wie folgt in this.user einzufügen:

app.use(function * setUserInContext (next) {
  this.user = this.req.user
  yield next
})

Wenn Sie sich nicht sicher sind, wie serializeUser und deserializeUser funktionieren, melden Sie sich einfach bei Twitter. @yvanscher

Yvanscher
quelle
Entschuldigen Sie die Nekropostierung hier, aber ich habe jetzt Bedenken, nachdem ich die Deserialisierungserklärung gelesen habe. Ich habe eine Frage dazu hier auf SO gepostet: stackoverflow.com/questions/54154047/…
Peter Kellner
Super hilfreich, aber immer noch Probleme beim Lesen des Benutzers von anderen Routen. Kann mir hier jemand helfen? stackoverflow.com/questions/60709882/…
Harry Lincoln