2013-03-25 1 views
18

Ho bisogno di una casella di controllo "Ricordami" quando effettui il login come this. E aggiungo un middleware prima di utilizzare il passaportoCome aggiungere "Ricordami" alla mia app con passaporto

app.use(function (req, res, next) { 
if (req.method == 'POST' && req.url == '/login') { 
    if (req.body.rememberme) { 
    req.session.cookie.maxAge = 1000 * 60 * 3; 
    } else { 
    req.session.cookie.expires = false; 
    } 
} 
next(); 
}); 
app.use(passport.initialize()); 
app.use(passport.session()); 

Non riesco ad accedere quando req.body.rememberme è vero e l'utente si ricorda quando req.body.rememberme è falso. Ho anche provato connect-ensure-login e ancora sbagliato.

e un'altra domanda: quando devo eliminare i cookie nel mio database e come?

:)

Altro codice è esattamente la stessa, come la guida del passaporto

percorso:

app.get('/', passport.authenticate('local', {failureRedirect: '/login'}), function (req, res) { res.redirect('/user/home'); }); 
app.post('/login', passport.authenticate('local', {failureRedirect: '/login'}), function (req, res) { res.redirect('/user/home'); }); 

sessioni:

passport.serializeUser(function(user, done) { 
var CreateAccessToken = function() { 
    var token = user.GenerateSalt(); 
    User.findOne({accessToken: token}, function(err, existingUser) { 
    if (err) return done(err); 
    if (existingUser) { 
     CreateAccessToken(); 
    } else { 
     user.set('accessToken', token); 
     user.save(function(err) { 
     if (err) return done(err); 
     return done(null, user.get('accessToken')); 
     }) 
    } 
    }); 
}; 
if (user._id) 
    CreateAccessToken(); 
}); 
passport.deserializeUser(function(token, done) { 
    User.findOne({accessToken: token}, function(err, user) { 
    if (err) return done(err); 
    return done(err, user); 
    }); 
}); 

e strategiche:

passport.use(new LocalStrategy(function(userId, password, done) { 
User.findOne().or([{username: userId}, {email: userId}]).exec(function(err, user) { 
    if (err) return done(err); 
    if (!user) { 
    return done(null, false, {message: 'Invalid password or username'}); 
    } 
    if (user.Authenticate(password)) { 
    return done(null, user); 
    } else { 
    return done(null, false, {message: 'Invalid password or username'}); 
    } 
}); 
})); 

Ho notato che Express aggiornerà il cookie solo quando il valore hash è cambiato. così ho modificato il codice del middleware

app.use(function (req, res, next) { 
    if (req.method == 'POST' && req.url == '/login') { 
     if (req.body.rememberme) { 
     req.session.cookie.maxAge = 1000 * 60 * 3; 
     req.session._garbage = Date(); 
     req.session.touch(); 
     } else { 
     req.session.cookie.expires = false; 
     } 
    } 
    next(); 
}); 

ora posso effettuare il login con "Remember Me", ma funziona solo su cromo e Firefox su Ubuntu. Non riesco ancora ad accedere con la casella di controllo "Remember Me" su Chrome e Firefox su Win7 e Android.

Ho verificato l'intestazione della risposta quando POST su "/ login" su chrome su win7 e aveva lo stesso campo "Set-Cookie" come su Ubuntu, perché non può funzionare?


Il tempo non è sincronizzato, quindi inserisco un campo di tempo extra.

$('#login').ajaxForm({beforeSubmit: function(arr, $form, option) { 
    arr.push({name: '__time', value: (new Date()).toGMTString()}); 
}}); 

e il middleware "RememberMe":

app.use(function (req, res, next) { 
    if (req.method == 'POST' && req.url == '/login') { 
     if (req.body.rememberme) { 
     req.session.cookie.maxAge = moment(req.body.__time).add('m', 3) - moment(); 
     req.session._garbage = Date(); 
     req.session.touch(); 
     } else { 
     req.session.cookie.expires = false; 
     } 
    } 
    next(); 
}); 
+0

non è questo in modo errato? Se 'rememberme == true' significa che il cookie non dovrebbe scadere?Dovresti postare più codice in quanto ti serve più di questi tre middleware – pfried

+0

Se 'rememberme == true' il cookie ottiene una scadenza (di 3 minuti in questo caso), altrimenti il ​​cookie è fatto per essere un cookie di sessione (scadente quando il browser la sessione è terminata). Ma sono d'accordo: è necessario più codice. – robertklep

+0

questo codice è molto confuso. Dovresti separare le preoccupazioni. Le funzioni 'serialize' e' deserialize' sono ony per ottenere un utente dal suo id (usa l'id del database) e serializzarlo su un cookie di sessione (l'id non sarà lì in chiaro se ti preoccupi). Non mescolare in qualche dubbio codice di sicurezza – pfried

risposta

1

Assicurarsi che app.use(express.bodyParser()) è posto sopra il middleware, come si fa affidamento su req.body.rememberme

25

Ho avuto esattamente lo stesso problema come te. Il seguente codice funziona per me:

app.post("/login", passport.authenticate('local', 
    { failureRedirect: '/login', 
     failureFlash: true }), function(req, res) { 
     if (req.body.remember) { 
      req.session.cookie.maxAge = 30 * 24 * 60 * 60 * 1000; // Cookie expires after 30 days 
     } else { 
      req.session.cookie.expires = false; // Cookie expires at end of session 
     } 
     res.redirect('/'); 
}); 
+0

Questo è esattamente ciò di cui avevo bisogno, grazie. –

+0

Ho modificato il tempo di esempio da 3 minuti (che è inferiore alla maggior parte delle sessioni) a 30 giorni. Stavo pensando che 3 minuti era la modalità non ricordo di me, e '... expires = false;' significato significa non scadere mai. – rjmunro

5

Esiste ora una strategia Passport per aggiungere la funzionalità di Remember Me scritta da Jared Hanson.

https://github.com/jaredhanson/passport-remember-me

Questo funziona mediante l'emissione di un unico ricordo-me Token durante ogni sessione che si consuma al via del prossimo (invalidante per un uso futuro.) Di conseguenza, questo è probabile che sia un altro soluzione sicura.

+0

Se la tua app è l'app koa.js, https://github.com/clthck/passport-remember-me ha funzionato bene per me. In realtà è un fork del repository originale di jaredhanson e aggiunge solo un supporto per l'app koa.js (insieme a [koa-passport] (https://github.com/rkusa/koa-passport)) – artificis

+0

Vale anche la pena notare che per true 'Remember Me' - avrai bisogno di una sorta di persistenza a lungo termine per i token, sia in una cache che in un database - altrimenti il ​​server li memorizzerebbe in memoria. Vuoi essere in grado di riavviare il server e avere ancora il ricordo che il token è valido – tcmoore