it-swarm.com.de

Passport-Login und dauerhafte Sitzung

Hintergrund

Ich habe eine MEAN-Anwendung mit CRUD-Funktionen, die vollständig mit dem Postboten getestet wurde. Ich habe mich schon seit einiger Zeit bemüht, das Login ohne Erfolg zu bestehen. Ich habe Folgendes gelesen und ausprobiert 

Ich konnte mich jedoch nur registrieren und einen Benutzer anmelden, ohne sich mit einer Sitzung anmelden zu müssen.

Meine App

Hier ist ein Link zum vollständigen Github-Repo (wenn Sie nach den neuesten Änderungen suchen, prüfen Sie den Zweig für die Entwicklung)

Mein Verständnis von Auth/Login

Hier ist mein Verständnis der Benutzeranmeldung mit Codebeispielen aus meinem Projekt und Screenshot der Postman-Ergebnisse sowie Konsolenprotokollen.

Reisepass einrichten

Ich habe die folgende auth.js-Datei, sie konfiguriert den Pass

var passport = require('passport');
var LocalStrategy = require('passport-local').Strategy;

module.exports = function(app, user){

  app.use(passport.initialize());
  app.use(passport.session());

  // passport config
  passport.use(new LocalStrategy(user.authenticate()));

  passport.serializeUser(function(user, done) {
    console.log('serializing user: ');
    console.log(user);
    done(null, user._id);
  });

  passport.deserializeUser(function(id, done) {
    user.findById(id, function(err, user) {
      console.log('no im not serial');
      done(err, user);
    });
  });
};

Diese wird in der Server-Datei gerne aufgerufen

//code before
var user    = require('./models/user.js');
var auth    = require('./modules/auth.js')(app, user);
// code after

Routing für Login

In meinen Routen habe ich die Login-Route wie folgt

router.post('/login', function(req, res, next) {

  passport.authenticate('local', function(err, user, info) {

    if (err) {
        return next(err);
    }

    if (!user) {
        return res.status(401).json({
            err: info
        });
    }

    req.logIn(user, function(err) {

        if (err) {
            return res.status(500).json({
                err: 'Could not log in user'
            });
        }

        res.status(200).json({
            status: 'Login successful!'
        });

    });
  })(req, res, next);
});

Diese Route funktioniert wie beim Postboten getestet Ich gebe die Details "joe" und "pass" ein und erhalte folgende Antwort.

 enter image description here

Wenn diese Route getroffen wird, können wir auch in der Konsole sehen, dass der Benutzer serialisiert ist.

 enter image description here

Was kommt als nächstes?

Hier verirre ich mich. Ich habe ein paar Fragen.

  1. Befindet sich der Benutzer jetzt in einer Sitzung auf meinem Server?
  2. Soll ich den req.session.passport.user an den Client zurücksenden?
  3. Benötige ich die Sitzungs-ID für alle zukünftigen Anfragen?

Sitzung testen

Ich habe ein zweites Routen-Setup zum Testen der Sitzung wie folgt

router.get('/checkauth', passport.authenticate('local'), function(req, res){

    res.status(200).json({
        status: 'Login successful!'
    });

});

Der Teil passport.authenticate('local') (dachte ich) ist da, um zu testen, ob die Benutzersitzung existiert, bevor der Zugriff auf die Route gewährt wird. Ich bekomme jedoch niemals eine Antwort von 200, wenn ich diese selbst nach einem Login ausführte.

Erwartet diese Route einen im Kopf übergebenen req.session.passport.user oder als Datenargument für eine http-Anforderung, für die eine Authentifizierung erforderlich ist?

Wenn ich etwas verpasst habe oder etwas falsch verstanden habe, teilen Sie mir dies bitte mit. Danke euch allen.

27
Joe Lloyd

Befindet sich der Benutzer jetzt in einer Sitzung auf meinem Server?

Nein, Sie müssen die express-session-Middleware vor app.use(passport.session()); verwenden, um die Sitzung tatsächlich im Speicher/in der Datenbank zu speichern. Diese Middleware ist für das Setzen von Cookies für Browser verantwortlich und konvertiert die von Browsern gesendeten Cookies in req.session-Objekt. PassportJS verwendet dieses Objekt nur, um den Benutzer weiter zu deserialisieren.

Soll ich den req.session.passport.user an den Client zurücksenden?

Wenn Ihr Client beim Login eine user-Ressource erwartet, sollten Sie dies tun. Ansonsten sehe ich keinen Grund, das Benutzerobjekt an den Client zu senden.

Benötige ich die Sitzungs-ID für alle zukünftigen Anfragen?

Ja, für alle zukünftigen Anforderungen ist die Sitzungs-ID erforderlich. Wenn Ihr Client jedoch ein Browser ist, müssen Sie nichts senden. Der Browser speichert die Sitzungs-ID als Cookie und sendet sie für alle nachfolgenden Anfragen, bis der Cookie abgelaufen ist. express-session liest dieses Cookie und fügt das entsprechende Sitzungsobjekt als req.session an.

Testen der Sitzung

passport.authenticate('local') dient zum Authentifizieren von Benutzeranmeldeinformationen im POST - Body. Sie sollten dies nur für die Login-Route verwenden.

Um jedoch zu überprüfen, ob der Benutzer auf allen anderen Routen authentifiziert ist, können Sie prüfen, ob req.user definiert ist.

function isAuthenticated = function(req,res,next){
   if(req.user)
      return next();
   else
      return res.status(401).json({
        error: 'User not authenticated'
      })

}
router.get('/checkauth', isAuthenticated, function(req, res){

    res.status(200).json({
        status: 'Login successful!'
    });
});
49
hassansin

Wie @ hassansin sagt, müssen Sie eine Middleware verwenden, die die Sitzungsverwaltung implementiert. Die Middleware passport.session () verbindet das Passport-Framework mit der Sitzungsverwaltung und implementiert die Sitzung nicht selbst. Sie können die express-session-Middleware verwenden, um die Sitzungsverwaltung zu implementieren. Sie müssen Ihre auth.js folgendermaßen ändern

var passport = require('passport');
var session = require('express-session');
var LocalStrategy = require('passport-local').Strategy;

module.exports = function(app, user){
  app.use(session({secret: 'some secret value, changeme'}));    

  app.use(passport.initialize());
  app.use(passport.session());

  // passport config
  passport.use(new LocalStrategy(user.authenticate()));

  passport.serializeUser(function(user, done) {
    console.log('serializing user: ');
    console.log(user);
    done(null, user._id);
  });

  passport.deserializeUser(function(id, done) {
    user.findById(id, function(err, user) {
      console.log('no im not serial');
      done(err, user);
    });
  });
};

Beachten Sie, dass das Session-Modul in diesem Fall den Speicher verwendet und nicht funktioniert, wenn Sie Ihre Anwendung skalieren und den Lastenausgleich anwenden. Wenn Sie diesen Entwicklungsstand erreichen, wird etwas wie der Sitzungsspeicher connect-redis benötigt.

Beachten Sie auch, dass Sie den geheimen Wert ändern müssen, der für den Session-Midleware-Aufruf verwendet wird, und denselben Wert für alle Anwendungsinstanzen verwenden.

9
yeiniel

Gemäß der Passport-Dokumentation wird req.user für den authentifizierten Benutzer festgelegt. Damit dies funktioniert, benötigen Sie das Modul express-session. Sie sollten nichts weiter brauchen als das, was Sie bereits haben, damit der Pass funktioniert.

Zum Testen der Sitzung können Sie über eine Middleware-Funktion verfügen, die prüft, ob der Benutzer req.user festgelegt ist. Wenn dies der Fall ist, wissen wir, dass der Benutzer authentifiziert ist. Wenn dies nicht der Fall ist, können Sie den Benutzer umleiten.

Sie könnten beispielsweise über eine Middleware-Funktion verfügen, die Sie für alle Routen verwenden können, die Sie authentifizieren möchten.

authenticated.js

module.exports = function (req, res, next) {
    // if user is authenticated in the session, carry on
    if (req.user) {
        next();
    }
    // if they aren't redirect them to the login page
    else {
        res.redirect('/login');
    }
};

Controller

var authenticated = require('./authenticated');

router.get('/protectedpage', authenticated, function(req, res, next) {
    //Do something here
});
1

Passport.js funktioniert nicht gut, da es die Sitzung auf dem Server speichert (fehlerhaft und nicht skalierbar). Sie möchten keine Sitzungsdaten auf dem Server speichern (ohne Status), da Sie dann Ihre Cluster skalieren und mehr Anforderungen bearbeiten können.

Wenn Sie sich den Code in der Passport.js-Bibliothek ansehen, gibt es nicht viel. Es kann tatsächlich schneller und effizienter sein, ihn selbst zu erstellen.

Hier ist ein Tutorial, das ich geschrieben habe, um besser mit Google zu verbinden .

0
Jack

Ich kenne keine Möglichkeit, alle vorhandenen Sitzungen zu überprüfen, aber Passport kümmert sich um die Ausgabe von Sitzungs-IDs. Überprüfen Sie nach der Anmeldung, ob auf Ihrem Testendpunkt "req.user" vorhanden ist

0
tcmoore