Was macht die Middleware passport.session ()?

125

Ich erstelle ein Authentifizierungssystem mit Passport.js mithilfe der einfachen Knotenauthentifizierung: Setup und lokales Lernprogramm .

Ich bin verwirrt darüber, was passport.session()tut.

Nachdem ich mit der verschiedenen Middleware express.session()herumgespielt hatte, wurde mir passport.session()klar , dass dies eine Sitzungs-ID über Cookies an den Client sendet, aber ich bin verwirrt darüber, was dies tut und warum es zusätzlich erforderlich ist express.session().

So richte ich meine Anwendung ein:

// Server.js konfiguriert die Anwendung und richtet den Webserver ein

//importing our modules
var express = require('express');
var app = express();
var port = process.env.PORT || 8080;
var mongoose = require('mongoose');
var passport = require('passport');
var flash = require('connect-flash');

var configDB = require('./config/database.js');

//Configuration of Databse and App

mongoose.connect(configDB.url); //connect to our database

require('./config/passport')(passport); //pass passport for configuration

app.configure(function() {

    //set up our express application

    app.use(express.logger('dev')); //log every request to the console
    app.use(express.cookieParser()); //read cookies (needed for auth)
    app.use(express.bodyParser()); //get info from html forms

    app.set('view engine', 'ejs'); //set up ejs for templating

    //configuration for passport
    app.use(express.session({ secret: 'olhosvermelhoseasenhaclassica', maxAge:null })); //session secret
    app.use(passport.initialize());
    app.use(passport.session()); //persistent login session
    app.use(flash()); //use connect-flash for flash messages stored in session

});

//Set up routes
require('./app/routes.js')(app, passport);

//launch
app.listen(port);
console.log("Server listening on port" + port);
Georges Krinker
quelle

Antworten:

139

passport.session() fungiert als Middleware zum Ändern des Anforderungsobjekts und zum Ändern des Benutzerswerts, der derzeit die Sitzungs-ID (aus dem Client-Cookie) ist, in das echte deserialisierte Benutzerobjekt.

Während die anderen Antworten einige gute Punkte hervorheben, dachte ich, dass einige spezifischere Details bereitgestellt werden könnten.

app.use(passport.session());

ist äquivalent zu

app.use(passport.authenticate('session'));

Wobei 'Sitzung' sich auf die folgende Strategie bezieht, die mit passportJS gebündelt ist.

https://github.com/jaredhanson/passport/blob/master/lib/strategies/session.js

Speziell die Zeilen 59-60:

var property = req._passport.instance._userProperty || 'user';
req[property] = user;

Wenn es im Wesentlichen als Middleware fungiert und den Wert der Eigenschaft 'user' im req-Objekt so ändert, dass die deserialisierte Identität des Benutzers enthalten ist. Damit dies korrekt funktioniert, müssen Sie serializeUserund deserializeUserFunktionen in Ihren benutzerdefinierten Code aufnehmen.

passport.serializeUser(function (user, done) {
    done(null, user.id);
});

passport.deserializeUser(function (user, done) {
    //If using Mongoose with MongoDB; if other you will need JS specific to that schema.
    User.findById(user.id, function (err, user) {
        done(err, user);
    });
});

Dadurch wird der richtige Benutzer aus der Datenbank gefunden und als Abschlussvariable an den Rückruf übergeben, done(err,user);sodass der obige Code im den passport.session()Benutzerwert im req-Objekt ersetzen und an die nächste Middleware im Stapel weiterleiten kann.

Lindsaymacvean
quelle
Hey, wie kann ich Benutzerdaten nur in der Sitzung speichern?
Ich
1
"in den Anforderungsheadern"? nein nur im
Anfrageobjekt
Ich habe festgestellt, dass, wenn die Sitzungsstrategie in der Lage ist, die Authentifizierung wiederherzustellen und den Benutzer zu deserialisieren. Trotzdem geht die Authentifizierung immer noch zur nächsten Strategie über, die in meinem Szenario die Facebook-Authentifizierung ist. Ich frage mich, wozu die Sitzungsstrategie gut ist, wenn sie weiterhin die folgenden Strategien aufruft, selbst wenn die Sitzung den Benutzer wiederherstellen kann.
Nishant
15

Aus der Dokumentation

In einer Connect- oder Express-basierten Anwendung ist die Middleware passport.initialize () erforderlich, um Passport zu initialisieren. Wenn Ihre Anwendung dauerhafte Anmeldesitzungen verwendet, muss auch die Middleware passport.session () verwendet werden.

und

Sitzungen

In einer typischen Webanwendung werden die zur Authentifizierung eines Benutzers verwendeten Anmeldeinformationen nur während der Anmeldeanforderung übertragen. Wenn die Authentifizierung erfolgreich ist, wird eine Sitzung über ein im Browser des Benutzers festgelegtes Cookie eingerichtet und verwaltet.

Jede nachfolgende Anforderung enthält keine Anmeldeinformationen, sondern das eindeutige Cookie, das die Sitzung identifiziert. Um Anmeldesitzungen zu unterstützen, serialisiert und deserialisiert Passport Benutzerinstanzen zur und von der Sitzung.

und

Beachten Sie, dass das Aktivieren der Sitzungsunterstützung völlig optional ist, obwohl dies für die meisten Anwendungen empfohlen wird. Wenn diese Option aktiviert ist, müssen Sie vor passport.session () express.session () verwenden, um sicherzustellen, dass die Anmeldesitzung in der richtigen Reihenfolge wiederhergestellt wird.

Josh C.
quelle
1
Vielen Dank für Ihre schnelle Antwort, aber das beantwortet meine Frage nicht. Beachten Sie außerdem, dass, wenn Sie eine Express-Anwendung haben und express.session () auf einem Client verwenden, der eine Verbindung zu Ihrem Express-Server herstellt (unabhängig davon, ob er authentifiziert ist oder nicht), er über ein Cookie eine Sitzung erhält. Dies ist unabhängig davon, ob er sich auf einer anmeldeschützten Seite Ihrer App befindet oder nicht. Ich würde immer noch gerne den Unterschied zwischen beiden Middleware kennen.
Georges Krinker
1
@GeorgesKrinker Es sind die Methoden serializeUser () und deserializeUser. Die Express-Middleware stellt die Sitzungsinformationen wieder her. Dies hängt jedoch nicht unbedingt damit zusammen, wie der Pass die Benutzerinformationen verwaltet. Dies muss erfolgen, nachdem die Sitzung per Express rehydriert wurde.
Josh C.
Nun, ich hatte den Eindruck, dass die Methoden serializeUser () und deserializeUser innerhalb der Routen auf authenticate () ausgeführt wurden.
Georges Krinker
@GeorgesKrinker Das glaube ich nicht. Wenn ich den Reisepass verwendet habe, habe ich beim Anmelden nur .authenticate angerufen.
Josh C.
app.post('/login', passport.authenticate('local'), ...
Josh C.
11

Während Sie PassportJsden Benutzer als Teil Ihrer Anmelde-URL validieren, benötigen Sie noch einen Mechanismus, um diese Benutzerinformationen in der Sitzung zu speichern und bei jeder nachfolgenden Anforderung abzurufen (dh den Benutzer zu serialisieren / deserialisieren).

Tatsächlich authentifizieren Sie den Benutzer bei jeder Anforderung, obwohl diese Authentifizierung nicht wie in der Anmeldeantwort nach einer Datenbank oder einem anderen suchen muss. Passport behandelt die Sitzungsauthentifizierung daher auch als eine weitere Authentifizierungsstrategie.

Und um diese Strategie zu verwenden - die benannt ist session, verwenden Sie einfach eine einfache Verknüpfung - app.use(passport.session()). Beachten Sie auch, dass Sie mit dieser speziellen Strategie aus offensichtlichen Gründen Serialisierungs- und Deserialisierungsfunktionen implementieren müssen.

uniwalker
quelle
11

Es authentifiziert einfach die Sitzung (die von gefüllt wird express.session()). Es ist äquivalent zu:

passport.authenticate('session');

wie im Code hier zu sehen ist:

https://github.com/jaredhanson/passport/blob/42ff63c/lib/authenticator.js#L233

Jared Hanson
quelle
6
Was meinst du? Es wird bei jeder Anforderung ausgeführt und verfügt nicht unbedingt über Anmeldeinformationen zur Authentifizierung. Würde es Ihnen etwas ausmachen, mir ein bisschen mehr Details über den Workflow zu geben, der bei jeder Anfrage stattfindet?
Georges Krinker
6
Ja, es wird bei jeder Anfrage ausgeführt. Die von Express generierte Sitzungs-ID ist eine eindeutige ID, die in etwa einem Authentifizierungstoken entspricht, das der Browser bei jeder Anforderung sendet. Die in dieser Sitzung gespeicherten Daten werden verwendet, um den Authentifizierungsstatus des Benutzers wiederherzustellen.
Jared Hanson
Hallo @JaredHanson Könnten Sie einen Blick auf nehmen diese . Ich konnte die Antwort nirgendwo finden?
Saras Arya
@JaredHanson Ich versuche, passport.js zur Authentifizierung bei einem weit verbreiteten Open Source-Autorisierungsserver zu verwenden, der OAuth2-kompatibel ist. Aber ich bekomme einen Fehler. Sind Sie bereit, zur Lösung des Problems beizutragen? Hier ist der Link: stackoverflow.com/questions/38176236/…
DollarCoffee
@JaredHanson: Was ich beobachte, ist, dass das mit passport.user-Informationen erweiterte Anforderungsobjekt direkt nach der Anmeldung über google-oauth verloren geht, wenn die nächste Anforderung für eine neue Seite auf der Site erfolgt. Ist das erwartetes Verhalten? Dann weiß ich nicht, wie ich die kürzlich angemeldeten Benutzerinformationen zurückerhalten kann.
user1102171