2013-02-22 8 views
15

Ich verwende Passport für die Authentifizierung in meiner App, und ich verwende auch Express. Zu meiner Frage zusammenfassen: Anmeldungs ​​Funktionalität arbeitet zunächst in Ordnung, aber nach jedes Sitzungszeiten des Benutzers aus, keine Benutzer können sich anmeldenNode.js Express Passport Cookie Ablauf

ich die Standard Lokale Strategie zur Authentifizierung verwende..

Ich werde umfassen als ein Beispiel wie möglich basierend auf meinem Setup gebärst

//------------- 
//Set up authentication with Passport 
//------------- 
var userModel = require('./models/user')(db); 
passport.use(new LocalStrategy(
    function(username, password, done) { 
     var errorMessage = 'Incorrect username/password combination.'; 
     userModel.GetUserByUsername(username, function(err, user) { 
      if (err) { return done(err); } 
      if (!user) { 
       return done(null, false, { message: errorMessage }); 
      } 

      user.validatePassword(password, function(isPasswordCorrect) { 
       if (!isPasswordCorrect) 
       { 
        return done(null, false, { message: errorMessage }); 
       } 

       //Update with login date 
       userModel.UpdateUserWithLogin(username, user.currentLoginTime, function(err){ 
        //if we have an error here, we should probably just log it 
        if(err) 
        { 
         console.log(err); 
        } 
       }); 

       return done(null, user); 
      }); 
     }); 
    } 
)); 

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

passport.deserializeUser(function(user, done) { 
    userModel.GetUserByUsername(user._id, function(err, user) { 
      done(err, user); 
     }); 
}); 

//------------- 
//Set up express and configure 
//------------- 
var sessionStore = new SkinStore(db); 
var app = express(); 

app.configure(function(){ 
    app.set('port', process.env.PORT || 3000); 
    app.set('views', __dirname + '/views'); 
    app.engine('html', consolidate.swig); 
    app.set('view engine', 'html'); 
    swig.init({ 
     root: '.', 
     allowErrors: true, // allows errors to be thrown and caught by express instead of suppressed 
     autoescape: false}); 

    app.use(express.logger('dev')); 

    app.use(express.bodyParser()); 
    app.use(express.methodOverride()); 
    app.use(express.cookieParser("[mysecrethere]")); 
    app.use(express.session({ store: sessionStore, 
          cookie: { expires : new Date(Date.now() + 3600000) } //1 Hour 
          })); 
    app.use(passport.initialize()); 
    app.use(passport.session()); 
    app.use(flash()); 
    app.use(expressValidator); 

    app.use(express.static(path.join(__dirname, 'public'))); 

    //Dynamic helpers 
    app.use(require('./helpers/DynamicHelpers')); 

    app.use(app.router); 
}); 

app.get('/login', routes.login); 
app.post('/login', passport.authenticate('local', {failureRedirect: '/login', 
               badRequestMessage: "Please enter username and password", 
               failureFlash: true }), 
               function(req, res) { 
                var targetUrl = req.session.pageAfterLogin; 
                delete req.session.pageAfterLogin; 
                res.redirect(targetUrl || '/account'); 
               }); 

app.get('/account', IsAuthenticated, routes.account.show); 

Und die IsAuthenticated Helferfunktion:

function IsAuthenticated(req,res,next){ 
    if(req.isAuthenticated()) 
    { 
     next(); 
    } 
    else 
    { 
     //save the requested page and then redirected 
     req.session.pageAfterLogin = req.url; 
     req.flash("error", "You must be logged in first!"); 
     res.redirect('/login'); 
    } 
} 

Was ich Debuggen finden kann, ist, dass nach erfolgreichem Authentifizierung (und nachdem ein Cookie abgelaufen ist), habe ich diese Logik (von oben) getroffen:

Wo kann ich sehen, dass die "req" die Sitzung ordnungsgemäß eingerichtet hat, mit Passport-Informationen ordnungsgemäß gespeichert. Dann passiert die Umleitung, die neue Anfrage hat keine Sitzungsinformationen gespeichert und hat eine völlig neue Session ID. Ich vermutete, dass auf dem Client kein Cookie gesetzt wurde, und das scheint der Fall zu sein, was das Fehlen konsistenter Sitzungen erklären sollte.

Allerdings kann ich nicht herausfinden warum kein neues Cookie gesetzt wird. Ist etwas nicht in Ordnung mit der Konfiguration der App, die angibt, warum dies geschieht?

Ich sollte hinzufügen, dass ein Neustart der Node.js-Instanz das Problem behebt, es ist nur nicht etwas, das in der Produktion tolerierbar wäre.

Danke.

UPDATE: Ich lief Fiddler, um zu sehen, was mit HTTP/S-Verkehr geschieht, und ich kann sehen, dass, wenn es anfangs funktioniert, ich bin im Browser ein Cookie gesetzt bekommen (ich versuchte mehr), der dann wurde bei nachfolgenden Anforderungen an den Server zurückgegeben.

Wenn es nicht funktioniert arbeiten, übergibt der Browser keine Cookies an den Server, und so sendet Node einen Set-Cookie-Header, der jedes Mal ein neues Cookie bereitstellt. Bis jetzt hatte ich kein Glück, die Ursache dafür zu bestimmen.

+0

Haben Sie überprüft, dass passport.deserializeUser ausgeführt wird, dass user._id vorhanden ist und dass Ihr Modell findet den Benutzer? Außerdem sollte serializeUser eine ID und nicht das Benutzerobjekt zurückrufen. –

+0

Ich konnte das (endlich) testen, und ich kann sehen, dass serializeUser ** ** aufgerufen wird. In nachfolgenden Umleitungen wird deserializeUser jedoch nicht ausgeführt. In serializeUser wurde der Benutzer ordnungsgemäß gefunden, es scheint einfach nicht zu bestehen. Und ich werde arbeiten, um die user._id anstelle des Benutzers zu serialisieren. Ich hatte das ursprünglich gemacht, wechselte aber aus irgendeinem Grund, den ich seitdem vergessen habe. – creativename

Antwort

24

Ich fand es heraus, obwohl ich die Antwort nicht liebe.

tl; dr; - Verwenden Sie maxAge statt abläuft.

Das Problem wurde durch das Ablaufdatum ausgelöst, das für jeden Cookie festgelegt wurde (der automatisch von Express festgelegt wird). Ich bemerkte, dass jedes Cookie, das gesetzt wurde, das gleiche Ablaufdatum hatte, das schließlich in der Vergangenheit endete und daher sofort ablief.

Die Ursache war das hier:

cookie: { expires : new Date(Date.now() + 3600000) } 

Das neue Datum nur einmal erstellt wurde, auf Serverstart. Das hat dazu geführt, dass das Verfallsdatum jedes Mal gleich ist.Basierend auf Code im ursprünglichen Beitrag kann ich nicht herausfinden, warum es nicht funktioniert und dennoch verwendet jedes Beispiel, das ich online gefunden habe, den exakt gleichen Code. Ich habe dies verifiziert, indem ich eine Funktion definiert habe, die dieses Datum erstellt hat und überprüft habe, dass es nur beim Serverstart aufgerufen wurde.

Um dieses Problem zu beheben, definiere ich maxAge statt "abläuft". maxAge dauert weniger Millisekunden als ein Datum und scheint das Ablaufdatum für alle Cookies korrekt festzulegen.

Ich würde gerne hören, wenn jemand erklären kann, warum dies in erster Linie passiert, da andere es erfolgreich zu verwenden scheinen. Irgendwelche Gedanken?

meinen Arbeitscode Siehe unten

app.configure(function(){ 
    app.set('port', process.env.PORT || 3000); 
    app.set('views', __dirname + '/views'); 
    app.engine('html', consolidate.swig); 
    app.set('view engine', 'html'); 
    swig.init({ 
     root: '.', 
     allowErrors: true, // allows errors to be thrown and caught by express instead of suppressed 
     autoescape: false}); 

    app.use(express.logger('dev')); 

    app.use(express.bodyParser()); 
    app.use(express.methodOverride()); 
    app.use(express.cookieParser("[mysecrethere]")); 
    app.use(express.session({ store: sessionStore, 
          cookie: { maxAge : 3600000 } //1 Hour 
          })); 
    app.use(passport.initialize()); 
    app.use(passport.session()); 
    app.use(flash()); 
    app.use(expressValidator); 

    app.use(express.static(path.join(__dirname, 'public'))); 

    //Dynamic helpers 
    app.use(require('./helpers/DynamicHelpers')); 

    app.use(app.router); 
}); 
+2

Danke @creativename. Ich habe seit Tagen mit diesem Problem zu kämpfen. Nachdem ich herausgefunden hatte, dass der Reisepass die Ablaufeigenschaft nicht aktualisiert hatte, dachte ich, es wäre unmöglich. Aber deine Lösung wirkt wie ein Zauber! –

+1

danke..das ist schwer zu sehen. macht jetzt Sinn. – Timmerz

+1

Ich glaube, dass ich auch auf dieses Problem stoße und Nutzer in einer Zeitzone auf der anderen Seite der Welt betrifft. –

-2

Set-Cookie-Namen-Wert, wobei die eine Zeichenfolge oder ein Objekt JSON konvertiert werden können. Die Pfadoption ist standardmäßig auf "/" eingestellt.

res.cookie('rememberme', '1', { expires: new Date(Date.now() + 900000), httpOnly: true });

Die maxAge Option eine zur Einstellung Bequemlichkeit Option ist "gültig bis" in Bezug auf die aktuelle Zeit in Millisekunden. Das Folgende entspricht dem vorherigen Beispiel.

res.cookie('rememberme', '1', { maxAge: 900000, httpOnly: true })

auch die Verbindung

http://expressjs.com/api.html#res.cookie

Verwandte Themen