2014-04-04 7 views
12

Nie mam strony logowania, ale mam formularz logowania, który pojawia się na każdej stronie. Chcę przekierować użytkownika z powrotem do tej samej strony byli na, niezależnie od tego, czy autoryzacja przebiegła pomyślnie (z odpowiednich komunikatów flash)Nodejs i PassportJs: Przekieruj oprogramowanie pośrednie po tym, jak paszport.authenticate nie zostanie wywołany, jeśli uwierzytelnienie się nie powiedzie

Weźmy następujący kod:

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); 
}); 

widzę tylko ostateczną middleware powyżej miano jeśli uwierzytelnienie zostanie przekazane. Jeśli się nie uda, wydaje się, że paszport przekierowuje mnie do/login w formie żądania pobrania. W mojej aplikacji ta strona nie istnieje.

Gdybym przekazać dodatkowe opcje obiekt jako parametr w funkcji paszport uwierzytelniać wtedy to działa:

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 

} 


)); 

Ale w ten sposób tracę możliwość wyboru, gdzie przekierować użytkownika do. Wygląda na to, że paszport przejmuje kontrolę nad miejscem przekierowania użytkownika, jeśli uwierzytelnienie nie powiedzie się. Jak mogę to naprawić? Czy to błąd? Czy uwierzytelnianie paszportowe musi być ostatnim oprogramowaniem pośredniczącym w łańcuchu, jeśli uwierzytelnienie nie powiedzie się?

To mój lokalny wywołanie funkcji strategia:

//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); 
    }); 

})); 

Odpowiedz

25

Można użyć niestandardowego uwierzytelniania zwrotnego, jak opisano w poprzednim akapicie tam 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); 
}); 
+0

To działa. Dzięki. (Uwaga dla siebie ... zawsze czytaj w instrukcji). – Paulie

+5

W twojej obronie, to raczej lapidarny podręcznik dla dużej koncepcji. (samemu stawiam podobne problemy ...) –

+0

Czy musimy uwzględnić w tym celu "strategię lokalną"? W moim przypadku daje mi błąd w nieznanej strategii lokalnej. – adi

3

biegałam w tym samym numerze, gdzie przekierowanie-połączenia, które następują udany Facebook Auth

  • passport.authenticate ('facebook', ..)

.. nie były honorowane.

Na podstawie "lokalnej" strategii paszportowej JS - i miłym przypomnieniem tego z @ploutch's answer here ..Uświadomiłem sobie klucz do uzyskania go do pracy wydaje się być w tej rozmowy:

req.logIn(user, function(err) { 
... 
} 

Na Facebooku, ta konfiguracja trasy pracował dla mnie:

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'); 
      });  
     } 
); 
+0

Tego nie rozumiem. Jeśli oprogramowanie pośredniczące paszport.authenticate ("facebook") zakończyło się pomyślnie, a twoja następna anonimowa funkcja zostanie wywołana (to jedyny sposób, w jaki można ją wywołać), to jesteś już zalogowany, a wywołanie req.login() jest zbyteczne. –

+0

@TimHardy Stwierdziłem, że ten rodzaj struktury jest bardzo trudny/mylący; w ogóle nie jestem fanem zawiłych konstrukcji uwierzytelniających .. * narzeka, narzeka *. Dla rozwiązania tutaj - kluczowymi słowami kluczowymi są * "ta konfiguracja trasy zadziałała dla mnie" * :) – gnB

0

pełnej odpowiedzi, w tym:

  • Oprogramowanie pośrednie do ustawienia redirectUrl
  • Wiadomości flash
  • Nie zwraca wartości, które nie będą sed

Wystarczy utworzyć wartość redirectTo w 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') 
} 

a następnie w swoim logowania 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); 
}); 
+0

Rozumiem, że nie dzwoni się dalej z sukcesem, co zwykle rejestruje użytkownika przy użyciu oprogramowania pośredniczącego do paszportów. Zamiast tego wywołujesz komendę req.login, która ręcznie rejestruje użytkownika i implementujesz niestandardowe przekierowanie. –

+0

Yep Tim, to dokładny opis. Może '.next()' jest bardziej idiomatyczne? Co myślisz? Możesz edytować wpis, o ile kod działa! – mikemaccana