Ich habe keine Anmeldeseite, aber ich habe ein Anmeldeformular, das auf jeder Seite angezeigt wird. Ich möchte den Benutzer auf dieselbe Seite zurückleiten, auf der er sich befand, unabhängig davon, ob die Authentifizierung erfolgreich war (mit entsprechenden Flash-Nachrichten).
Nimm den folgenden Code:
app.post('/login', validateLogin, passport.authenticate('local-login'), function(req, res) {
var redirectUrl = '/';
if(req.body.to.length > 0){
redirectUrl = req.body.to;
}
console.log("THIS IS ONLY CALLED IF passport.authenticate() IS SUCCESSFUL");
res.redirect(redirectUrl);
});
Ich sehe nur die letzte Middleware, die aufgerufen wird, wenn die Authentifizierung bestanden wird. Wenn dies fehlschlägt, wird der Pass scheinbar zu/login in Form einer Get-Anfrage umgeleitet. In meiner App existiert diese Seite nicht.
Wenn ich in der Passport-Authentifizierungsfunktion ein zusätzliches Optionsobjekt als Parameter übergeben habe, funktioniert dies:
app.post('/login', validateLogin, passport.authenticate('local-login', {
successRedirect : '/', // redirect to the secure profile section
failureRedirect : '/signup', // redirect back to the signup page. THIS IS JUST FOR TESTING TO SEE IF THE REDIRECT ON FAIL WORKS.
failureFlash : true, // allow flash messages
}
));
Dabei verliere ich jedoch die Möglichkeit zu wählen, wohin der Benutzer umgeleitet werden soll. Es scheint, dass der Pass die Kontrolle darüber übernimmt, wohin der Benutzer weitergeleitet wird, falls die Authentifizierung fehlschlägt. Wie kann ich das beheben? Oder ist es ein Fehler? Muss die Passport-Authentifizierung die letzte Middleware in der Kette sein, wenn die Authentifizierung fehlschlägt?
Dies ist mein lokaler Strategiefunktionsaufruf:
//LOCAL LOGIN
passport.use('local-login', new LocalStrategy({
// by default, local strategy uses username and password, we will override with email
usernameField : 'email',
passwordField : 'password',
passReqToCallback : true // allows us to pass back the entire request to the callback
},
function(req, email, password, done) { // callback with email and password from our form
console.log("IN PASSPORT");
if(email.length == 0 || password.length == 0){
console.log("FIELDS ARE EMPTY");
return done(null, false, req.flash('loginMessage', 'Fill in all values.'));
}
// find a user whose email is the same as the forms email
// we are checking to see if the user trying to login already exists
User.findOne({ 'local.email' : email }, function(err, user) {
// if there are any errors, return the error before anything else
if (err){
return done(err);
console.log("db err");
}
// if no user is found, return the message
if (!user){
console.log("not user");
return done(null, false, req.flash('loginMessage', 'Incorrect details.')); // req.flash is the way to set flashdata using connect-flash
}
// if the user is found but the password is wrong
if (!user.validPassword(password)){
console.log("invalid pw");
return done(null, false, req.flash('loginMessage', 'Incorrect details.')); // create the loginMessage and save it to session as flashdata
}
// all is well, return successful user
console.log("All OK");
return done(null, user);
});
}));
Sie könnten einen benutzerdefinierten Authentifizierungsrückruf verwenden, wie im letzten Absatz beschrieben http://passportjs.org/guide/authenticate/ .
app.post('/login', function(req, res, next) {
passport.authenticate('local', function(err, user, info) {
if (err) { return next(err); }
// Redirect if it fails
if (!user) { return res.redirect('/login'); }
req.logIn(user, function(err) {
if (err) { return next(err); }
// Redirect if it succeeds
return res.redirect('/users/' + user.username);
});
})(req, res, next);
});
Ich bin auf die gleiche Ausgabe gestoßen, in der die Weiterleitungen anrufen, die auf erfolgreiche Facebook-Authentifizierung folgen
.. wurden nicht geehrt.
Basierend auf 'local' passportJS Strategy - und einer schönen Erinnerung an die Antwort von @ploutch hier .. Ich erkannte, dass der Schlüssel für die Umsetzung in dieser Aufforderung zu liegen scheint:
req.logIn(user, function(err) {
...
}
Für Facebook funktionierte dieser Routenaufbau für mich:
app.get(
'/auth/facebook/callback',
passport.authenticate
(
'facebook',
{ failureRedirect: '/fbFailed' }
),
function(req, res)
{
var user = myGetUserFunc(); // Get user object from DB or etc
req.logIn(user, function(err) {
if (err) {
req.flash('error', 'SOMETHING BAD HAPPEND');
return res.redirect('/login');
}
req.session.user = user;
// Redirect if it succeeds
req.flash('success', 'Fb Auth successful');
return res.redirect('/user/home');
});
}
);
Vollständige Antwort, einschließlich:
Erstellen Sie einfach einen redirectTo
-Wert in Ihrer loginRequired
-Middleware:
var loginRequired = function(req, res, next) {
if ( req.isAuthenticated() ) {
next();
return
}
// Redirect here if logged in successfully
req.session.redirectTo = req.path;
res.redirect('/login')
}
Und dann in deinem Login POST:
router.post('/login', function(req, res, next) {
passport.authenticate('local', function(err, user, info) {
if ( err ) {
next(err);
return
}
// User does not exist
if ( ! user ) {
req.flash('error', 'Invalid email or password');
res.redirect('/login');
return
}
req.logIn(user, function(err) {
// Invalid password
if ( err ) {
req.flash('error', 'Invalid email or password');
next(err);
return
}
res.redirect(req.session.redirectTo || '/orders');
return
});
})(req, res, next);
});