
Jeffrey Chen
Ich habe Probleme, mein System dazu zu bringen, sich mit PassportJS abzumelden. Es scheint, dass die Abmelderoute aufgerufen wird, die Sitzung jedoch nicht entfernt wird. Ich möchte, dass 401 zurückgegeben wird, wenn der Benutzer nicht in einer bestimmten Route angemeldet ist. Ich rufe authenticateUser an, um zu prüfen, ob der Benutzer angemeldet ist.
Danke vielmals!
/******* This in index.js *********/
// setup passport for username & passport authentication
adminToolsSetup.setup(passport);
// admin tool login/logout logic
app.post("/adminTool/login",
passport.authenticate('local', {
successRedirect: '/adminTool/index.html',
failureRedirect: "https://stackoverflow.com/",
failureFlash: false })
);
app.get('/adminTool/logout', adminToolsSetup.authenticateUser, function(req, res){
console.log("logging out");
console.log(res.user);
req.logout();
res.redirect("https://stackoverflow.com/");
});
// ******* This is in adminToolSetup ********
// Setting up user authentication to be using user name and passport as authentication method,
// this function will fetch the user information from the user name, and compare the password for authentication
exports.setup = function(passport) {
setupLocalStrategy(passport);
setupSerialization(passport);
}
function setupLocalStrategy(passport) {
passport.use(new LocalStrategy(
function(username, password, done) {
console.log('validating user login');
dao.retrieveAdminbyName(username, function(err, user) {
if (err) { return done(err); }
if (!user) {
return done(null, false, { message: 'Incorrect username.' });
}
// has password then compare password
var hashedPassword = crypto.createHash('md5').update(password).digest("hex");
if (user.adminPassword != hashedPassword) {
console.log('incorrect password');
return done(null, false, { message: 'Incorrect password.' });
}
console.log('user validated');
return done(null, user);
});
}
));
}
function setupSerialization(passport) {
// serialization
passport.serializeUser(function(user, done) {
console.log("serialize user");
done(null, user.adminId);
});
// de-serialization
passport.deserializeUser(function(id, done) {
dao.retrieveUserById(id, function(err, user) {
console.log("de-serialize user");
done(err, user);
});
});
}
// authenticating the user as needed
exports.authenticateUser = function(req, res, next) {
console.log(req.user);
if (!req.user) {
return res.send("401 unauthorized", 401);
}
next();
}
Brices Antwort ist großartig, aber mir ist noch eine wichtige Unterscheidung aufgefallen; Der Passport-Leitfaden schlägt die Verwendung vor .logout()
(auch alias .logOut()
) als solche:
app.get('/logout', function(req, res){
req.logout();
res.redirect("https://stackoverflow.com/"); //Can fire before session is destroyed?
});
Aber wie oben erwähnt, ist dies unzuverlässig. Ich fand, dass es sich wie erwartet verhielt, als ich Brices Vorschlag wie folgt umsetzte:
app.get('/logout', function (req, res){
req.session.destroy(function (err) {
res.redirect("https://stackoverflow.com/"); //Inside a callback… bulletproof!
});
});
Hoffe das hilft!

Brice
Bin auf das gleiche Problem gestoßen. Verwenden req.session.destroy();
Anstatt von req.logout();
funktioniert, aber ich weiß nicht, ob dies die beste Methode ist.
session.destroy
möglicherweise nicht ausreicht, um sicherzustellen, dass der Benutzer vollständig abgemeldet ist, müssen Sie auch das Sitzungscookie löschen.
Das Problem hier ist, dass, wenn Ihre Anwendung auch als API für eine Single-Page-App verwendet wird (nicht empfohlen, aber ziemlich häufig), dann einige Anfragen von Express verarbeitet werden können, die vor dem Abmelden begonnen und nach dem Abmelden enden. Wenn dies der Fall wäre, stellt diese länger laufende Anfrage die Sitzung in redis wieder her, nachdem sie gelöscht wurde. Und weil der Browser immer noch das gleiche Cookie hat, werden Sie beim nächsten Öffnen der Seite erfolgreich angemeldet.
req.session.destroy(function() {
res.clearCookie('connect.sid');
res.redirect("https://stackoverflow.com/");
});
Das ist das, was vielleicht sonst passiert:
- Req 1 (jede Anfrage) wird empfangen
- Req 1 lädt die Sitzung von Redis in den Speicher
- Abmeldeanforderung erhalten
- Logout req lädt Sitzung
- Abmeldeanforderung zerstört Sitzung
- Abmeldeanforderung sendet Weiterleitung an den Browser (Cookie wird nicht entfernt)
- Req 1 schließt die Verarbeitung ab
- Req 1 speichert die Sitzung aus dem Speicher in redis
- Der Benutzer öffnet die Seite ohne Anmeldedialog, da sowohl das Cookie als auch die Sitzung vorhanden sind
Idealerweise müssen Sie die Token-Authentifizierung für API-Aufrufe verwenden und nur Sitzungen in der Web-App verwenden, die nur Seiten lädt, aber selbst wenn Ihre Web-App nur zum Abrufen von API-Token verwendet wird, ist diese Race-Bedingung immer noch möglich.
Ich hatte das gleiche Problem, und es stellte sich heraus, dass es überhaupt kein Problem mit den Passport-Funktionen war, sondern eher mit der Art und Weise, wie ich meine anrief /logout
Route. Ich habe fetch verwendet, um die Route aufzurufen:
(Schlecht)
fetch('/auth/logout')
.then([other stuff]);
Es stellt sich heraus, dass dabei keine Cookies gesendet werden, sodass die Sitzung nicht fortgesetzt wird, und ich denke, das res.logout()
wird auf eine andere Sitzung angewendet? Auf jeden Fall behebt es Folgendes, wenn Sie Folgendes tun:
(Gut)
fetch('/auth/logout', { credentials: 'same-origin' })
.then([other stuff]);

abitofcode
Ich hatte die gleichen Probleme, Capital O hat es behoben;
app.get('/logout', function (req, res){
req.logOut() // <-- not req.logout();
res.redirect("https://stackoverflow.com/")
});
Edit: Das ist kein Thema mehr.

Venryx
Ich habe beides verwendet req.logout()
und req.session.destroy()
und funktioniert gut.
server.get('/logout', (req, res) => {
req.logout();
req.session.destroy(()=>{
res.redirect("https://stackoverflow.com/");
});
});
Nur um zu erwähnen, dass ich Redis als Sitzungsspeicher verwende.

Charlie Fisch
Ich hatte kürzlich dasselbe Problem und keine der Antworten hat das Problem für mich behoben. Könnte falsch sein, aber es scheint mit einer Rennbedingung zu tun zu haben.
Das Ändern der Sitzungsdetails in die folgenden Optionen scheint das Problem für mich behoben zu haben. Ich habe es jetzt ungefähr 10 Mal oder so getestet und alles scheint richtig zu funktionieren.
app.use(session({
secret: 'secret',
saveUninitialized: false,
resave: false
}));
Im Grunde habe ich mich gerade verändert saveUninitialized
und resave
aus true
zu false
. Das scheint das Problem behoben zu haben.
Nur als Referenz verwende ich den Standard req.logout();
Methode in meinem Abmeldepfad. Ich verwende die Sitzungszerstörung nicht, wie andere Leute erwähnt haben.
app.get('/logout', function(req, res) {
req.logout();
res.redirect("https://stackoverflow.com/");
});
10182000cookie-checkWarum entfernt PassportJS in Node die Sitzung beim Abmelden nichtyes
In meinem Code rufe ich an
req.logOut()
mit Großbuchstaben O, aber in Bezug auf die führen Dein Code sollte auch funktionieren.– Balas
11. Januar 2013 um 12:10 Uhr
Ich habe viele Lösungen ausprobiert, aber keine davon hat bei mir funktioniert. Schließlich habe ich versucht, das Paket [email protected] auf [email protected] zu aktualisieren, und es funktioniert!
– prisan
8. April 2018 um 2:01 Uhr