2013-03-26 2 views
5

Ich versuche, redis mit Express verwenden, um eine Benutzeranmeldung und Sitzung zu erstellen. Ich teste die Route dieses curl Skript:Node.js/express - mit Pass mit redis, Sitzung nicht autorisierte

curl -d 'email=testEmail&password=testPass' http://localhost:3000/users/session 

Wenn ich das tue, Pass funktioniert gut durch Serialisierung, und dann kehrt es http 302. Ich habe nicht herausgefunden, was es tut, nachdem die Serialisierung, aber wenn ich versuche, es im Browser mit meiner Login-HTML-Formular statt Curl, zeigt es mir "Unauthorized" 401, und ich sehe keine meiner Konsolen-Logs. Hier ist mein app.js:

var express = require('express') 
    , fs = require('fs') 
    , cons = require('consolidate') 
    , http = require('http') 
    , flash = require('connect-flash') 
    , passport = require('passport') 
    , RedisStore = require("connect-redis")(express) //for sessions (instead of MemoryStore) 
    , redis = require('redis') 
    , env = process.env.NODE_ENV || 'development' 
    , config = require('./config/config')[env] 
    , db = redis.createClient(config.db.port, config.db.host); 

db.select(config.db.users) 
db.auth(config.db.auth); 

var app = express(); 

//require passport strategies (see code block below) 
require('./config/passport')(passport, config, app) 

app.use('/assets', express.static(__dirname + '/public')); 
app.use('/', express.static(__dirname + '/')); 
app.set('views', __dirname + '/views'); 
app.set('view engine', 'html'); 

app.configure(function(){ 
    app.set('config', config); 
    app.set('db', db); 
    app.set('port', process.env.PORT || 3000); 
    app.engine('.html', cons.swig); 
    app.use(express.logger('dev')) 
    app.use(express.favicon(__dirname + '/public/img/favicon.ico')); 
    app.use(express.cookieParser()) 
    app.use(express.bodyParser()) //enables req.body 
    app.use(express.methodOverride()) //enables app.put and app.delete (can also just use app.post) 
    app.use(express.session({ 
     secret: 'topsecret', 
     cookie: {secure: true, maxAge:86400000}, 
     store: new RedisStore({ 
      client:db, 
      secret:config.db.auth 
     }) 
    })); 

    app.use(flash()) 
    app.use(passport.initialize()) 
    app.use(passport.session()) 
    app.use(app.router) 
}); 

// Bootstrap routes 
require('./config/routes')(app, passport); 

http.createServer(app).listen(app.get('port'), function(){ 
    console.log("Express server listening on port " + app.get('port')+', mode='+env); 
}); 

und die Sitzung POST Route:

app.post('/users/session', passport.authenticate('local', {successRedirect: '/', failureFlash: 'Invalid email or password.', successFlash: 'Welcome!'}), users.session); 

ich wirklich nur Beispiele für Pass mit mongodb finden konnte, so dass ich bin mir nicht sicher über die folgenden. Ich versuche, um einen Benutzer zu finden, aber ich bin mir nicht sicher über die Rückrufe oder was Pass mit dem Benutzer Informationen zu tun, wenn ich fertig Rückkehr:

passport.use(new LocalStrategy({ usernameField: 'email', passwordField: 'password' }, 
    function(email, password, done) { 

     var db = app.get('db') 
     var multi = db.multi(); 

     db.get('email:'+email, function(err, uid){ 
      if (err) { console.log(err); return err } 
      if (!uid) { console.log('no uid found'); return null } 

      console.log('found '+uid) 
      db.hgetall('uid:'+uid, function(err, user){ 
       if (err) { console.log(err); return err } 
       if (!user) { 
        console.log('unkwn usr') 
        return done(null, false, { message: 'Unknown user' }) 
       } 

       if (password != user.password) { 
        console.log('invalid pwd') 
        return done(null, false, { message: 'Invalid password' }) 
       } 
       console.log('found user '+user) //I see this fine with curl, but no logs with browser 
       return done(null, user) 
      }); 
     });  
    } 
)) 

Passport-Serialisierung:

passport.serializeUser(function(user, done) { 
    console.log('passport serializing...'+user.name) 
    done(null, user.name) //no idea what happens to it after this. returns a 302 with curl, and 401 with browser 
}) 

Warum tut dies anders mit einem Browser als mit Curl? Jede Hilfe oder Kommentare sehr geschätzt!

+0

Der Unterschied ist, dass Ihr Browser einen (übrig gebliebenen) Session-Cookie sendet. Versuchen Sie, Ihren Browser im Modus "Incognito/Privat" auszuführen. Implementieren Sie auch 'pass.deserializeUser'? Wenn nicht, solltest du. – robertklep

+0

Versucht es mit Inkognito-Modus und gelöschten Cache/Cookies, gleiche Ergebnisse. Ich bin noch nicht an dem Punkt angelangt, an dem ich den deserializeUser schon brauchen würde, ich glaube, das ist für das Entfernen der Sitzung, richtig? Es zeigt immer noch "Unauthorized", wenn ich einen Browser verwende und keine meiner console.logs angezeigt werden. –

Antwort

1

Ich habe es herausgefunden! Um Pass mit jede Datenbank (nicht nur Mongo) zu verwenden, würde ich empfehlen, es mit einem Dummy-Benutzer zuerst zu versuchen. Hier ist was ich getan habe.

Login Form (login.html):

<form method="post" action="http://localhost:3000/users/session" name="loginform"> 
    <input id="login_input_username" type="text" name="email" /> 
    <input id="login_input_password" type="password" name="password" autocomplete="off" /> 
    <input type="submit" name="login" value="Submit" /> 
</form> 

Routing (route.js):

app.post('/users/session', passport.authenticate('local'), 
    function(req, res){ 
     res.end('success!'); 
    }); 

Passport Lokale Strategie Setup (passport.js):

passport.use(new LocalStrategy({ usernameField: 'email', passwordField: 'password' }, 
    function(email, password, done) { 
     //find user in database here 
     var user = {id: 1, email:'test', password:'pass'}; 
     return done(null, user); 
    } 
)); 

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

passport.deserializeUser(function(id, done) { 
    //find user in database again 
    var user = {id: 1, email:'test', password:'pass'}; 
    done(null, user); 
}) 

Obwohl ich mich frage, ob es notwendig ist, Benutzer in meiner Datenbank zweimal zu finden, oder wenn ich Deserialize falsch benutze.

+6

Der Zweck von 'serializeUser' besteht darin, eine Form von identifizierender Information für den Benutzer in der Sitzung zu speichern; 'deserializeUser' verwendet diese Informationen, um die vollständigen Benutzerinformationen erneut abzurufen. Sie können entweder das gesamte Benutzerobjekt in der Sitzung speichern (damit Sie die Datenbank nicht erneut danach abfragen müssen) oder eine ID speichern (in diesem Fall müssen Sie die Datenbank in 'deserializeUser' abfragen, um die ID aufzulösen zu einem Benutzerdatensatz). Es hängt jedoch davon ab, ob das Benutzerobjekt in der Sitzung so wie es ist gespeichert werden kann. – robertklep

+1

(Auch wenn Sie das gesamte Benutzerobjekt speichern, kann es von den Benutzerinformationen in der Datenbank abweichen, wenn sich diese seit der letzten Dateneingabe des Benutzers in die Sitzung geändert haben) – robertklep

+0

Hmm, wenn ich die Datenbank nach de frage Serialisierung, und der Benutzer hat etwas geändert (sagen Sie ihren Profilnamen), dann wird die serialisierte Cookie-Version nicht übereinstimmen, was in der Datenbank ist. Bedeutet das nicht, dass die Sitzung ungültig ist (in letzterem Fall)?und wollen wir nicht davon absehen, die db auf deserialize abzufragen? –