2014-10-16 6 views
8

Używam pliku paszport.js i chcę wysłać wiadomość, jeśli pola formularza są puste. Ale nie wiem, jak to zrobić, ponieważ paszport nie uruchamia strategii oddzwaniania, jeśli ich nie ma. Naprawdę chcę, aby ten przypadek użycia był bardziej przejrzysty i nie chcę modyfikować paszportu. Czuję, że jest sposób, żeby to zrobić, ale nie wiem gdzie! Próbowałem użyć wywołania zwrotnego trasy (app.post), ale nie działa tak, jak próbowałem.Uwierzytelnianie Node.js za pomocą usługi Passport: Jak wysłać wiadomość, jeśli brakuje pola?

Oto prototyp funkcja uwierzytelnienia:

Strategy.prototype.authenticate = function(req, options) { 
    options = options || {}; 
    var username = lookup(req.body, this._usernameField) || lookup(req.query, this._usernameField); 
    var password = lookup(req.body, this._passwordField) || lookup(req.query, this._passwordField); 
    // here is my problem 
    if (!username || !password) { 
    return this.fail({ message: options.badRequestMessage || 'Missing credentials' }, 400); 
    } 

    var self = this; 

    function verified(err, user, info) { 
    if (err) { return self.error(err); } 
    if (!user) { return self.fail(info); } 
    self.success(user, info); 
    } 

    try { 
    if (self._passReqToCallback) { 
     this._verify(req, username, password, verified); 
    } else { 
     this._verify(username, password, verified); 
    } 
    } catch (ex) { 
    return self.error(ex); 
    } 
}; 

Oto moja strategia:

passport.use('local-login', new LocalStrategy({ 
     usernameField : 'email', 
     passwordField : 'password', 
     passReqToCallback : true 
    }, 
    function(req, email, password, done) { 
     // ... 
     console.log("Hello"); 
     User.findOne({ 'local.email' : email }, function(err, user) { 
      if (err) 
       return done(err); 

      // if no user is found, return the message 
      if (!user) 
       return done(null, false, req.flash('loginMessage', 'Pas d\'utilisateur avec ce login.')); // 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)) 
       return done(null, false, req.flash('loginMessage', 'Oops! Mauvais password.')); // create the loginMessage and save it to session as flashdata 

      // all is well, return successful user 
      return done(null, user); 
     }); 

    })); 

I wreszcie moja droga:

app.get('/login', function(req, res) { 

    // render the page and pass in any flash data if it exists 
    res.render('login', { title: "Connexion", message: req.flash('loginMessage') }); 
}); 

// process the login form 
    app.post('/login', passport.authenticate('local-login', { 
     successRedirect : '/profile', // redirect to the secure profile section 
     failureRedirect : '/login', // redirect back to the signup page if there is an error 
     failureFlash : true // allow flash messages 
    }, function(err, user, info) { 
     // Was trying this callback, does'nt work, post callback maybe ? 
     console.log("Hello"); 
    })); 
+0

gdzie jest twój jade lub szablon? powinieneś sprawdzić 'wiadomość' i wyświetlić, jeśli jest obecny – anvarik

+0

Precyzja: Rzecz w tym, że jest wiadomość flash, gdy użytkownik lub hasło jest błędne, ale nie wtedy, gdy pola są puste. I nie mogę tego zrobić ponieważ wywołanie zwrotne w strategii nie jest wywoływane w tym scenariuszu przez paszport (zobacz protokół uwierzytelniania). Nie chcę włamać się do kodu paszportowego, musi być jakiś sposób. –

+0

return this.fail ({message: options.badRequestMessage || 'Missing credentials'}, 400); <- to jest zwracane zamiast tego i nie wiem jak mogę to uzyskać, na przykład w funkcji wywołania zwrotnego app.post. –

Odpowiedz

12

Nie powinieneś dzwonić pod numer req.flash w swoim oddzwo mieniu zwrotnym. Zamiast tego powinieneś zwrócić wiadomość as shown in the documentation. Paszport spowoduje, że wiadomość powróci do wiadomości flash, gdy failureFlash: true.

zmienione zweryfikować callback:

passport.use('local-login', new LocalStrategy({...}, 
    function(email, password, done) { 
     User.findOne({ 'local.email' : email }, function(err, user) { 
      if (err) 
       return done(err); 
      if (!user) 
       return done(null, false, {message: 'Pas d\'utilisateur avec ce login.'}); 
      if (!user.validPassword(password)) 
       return done(null, false, {message: 'Oops! Mauvais password.'}); 
      return done(null, user); 
     }); 

    })); 

i tras:

app.get('/login', function(req, res) { 
    console.log(req.flash('error')); 
    res.send(); 
}); 

app.post('/login', passport.authenticate('local-login', { 
    successRedirect : '/profile', 
    failureRedirect : '/login', 
    failureFlash : true 
})); 

Edit:

Oto przykład całkowicie pracy: https://gist.github.com/vesse/9e23ff1810089bed4426

+0

uuh. To nie rozwiązuje mojego problemu (puste pola cf op i op komentarzy), dziękuję za odpowiedź w dowolny sposób. flash nie jest zdefiniowany, jeśli zmienię swój kod zgodnie z sugestią. –

+1

Jest też coś jeszcze nie tak. Dodałem link do istoty zawierającej w pełni działający przykład. – vesse

+0

Niedawno miałem ten problem. Spojrzałem na twój punkt widzenia i zauważyłem kilka rzeczy, których mi brakowało i to działa idealnie. Dzięki za pomoc! @vesse – PourMeSomeCode

3

Musisz ustawić badRequestMessage i ustawić failureFlash: true.

Jak to:

passport.authenticate('login', { 
    successRedirect : '/', 
    failureRedirect : '/login', 
    badRequestMessage : 'Missing username or password.', 
    failureFlash: true 
}) 
3

To stare pytanie, ale miałem problem ze znalezieniem odpowiedzi. Mam nadzieję, że to pomoże innym.


myślę the documentation jest trochę niekompletny, jeśli chodzi o użyciu connect-flash. Mówią:

Uwaga: Używanie wiadomości flash wymaga funkcji req.flash(). Express 2.x dostarczył tę funkcję, jednak został usunięty z Express 3.x. Zaleca się użycie oprogramowania pośredniego connect-flash, aby zapewnić tę funkcję podczas korzystania z programu Express 3.x.

Jednak nie ma wzmianki o używaniu polecenia req.flash w wywołaniu zwrotnym done(). Opierając się na numerze scotch.io tutorial, należy zadzwonić pod numer zadzwonić pod numer req.flash(). Mi to pasuje.

// In your strategy 
... 
if (user) { 
    return done(null, false, req.flash('loginMessage','Pas d\'utilisateur avec ce login.')); 
... 

Oczywiście musisz użyć passReqToCallback. Upewnij się również, że failureFlash jest ustawiony na true. OP robi już to poprawnie.

Teraz możesz sprawdzić wiadomość flash na trasie. Zauważ, że connect-flash wysyła tablicę wiadomości. To może być problem z OP, jeśli jego szablon oczekuje ciągu.

// In your routes 
app.get('/login', function(req, res) { 

    // Test flash messages in the console 
    console.log(req.flash('loginMessage')); // This returns an array 
    console.log(req.flash('loginMessage')[0]); // This returns a string 

    // render the page and pass in any flash data if it exists 
    res.render('login', { 
     title: "Connexion", 
     message: req.flash('loginMessage')[0] // Don't forget the index! 
    }); 

}); 

Jeśli istnieje szansa posiadania wielu wiadomości logowania na stronie, przejść całą req.flash('loginMessage') tablicy i iterację go w swoim szablonie. Poniżej znajduje się przykład z użyciem nunjucks.


protip:

Jeśli masz wiele tras z komunikatów błyskowych, zawsze można ustawić je res.locals w trasie middleware. Nie będzie to kolidować z innymi lokalnymi użytkownikami, takimi jak title. Oto moja implementacja, przy użyciu bootstrap alerts.

W mojej strategii:

... 
if (!user){ 
    return done(null, false, req.flash('danger','No account exists for that email.')); 
} 
... 

W moich routes.js:

// Set flash messages 
router.get('*', function(req,res,next){ 
    res.locals.successes = req.flash('success'); 
    res.locals.dangers = req.flash('danger'); 
    res.locals.warnings = req.flash('warning'); 
    next(); 
}); 

// Login route 
app.get('/login', function(req, res) { 
    res.render('login', { title: 'Login'}); 
}); 

W moim nunjucks szablonu bazowego:

<!--Messages--> 
{% for danger in dangers %} 
    <div class='header alert alert-danger alert-dismissible'> 
     <strong><i class="fa fa-exclamation-circle"></i> ERROR:</strong> {{ danger | safe }} 
     <a href="#" class='close' data-dismiss="alert" aria-label="close"><i class='fa fa-times'></i></a> 
    </div> 
{% endfor %} 
{% for warning in warnings %} 
    <div class='header alert alert-warning alert-dismissible'> 
     <strong><i class="fa fa-check-circle"></i> Warning:</strong> {{ warning | safe }} 
     <a href="#" class='close' data-dismiss="alert" aria-label="close"><i class='fa fa-times'></i></a> 
    </div> 
{% endfor %} 
{% for success in successes %} 
    <div class='header alert alert-success alert-dismissible'> 
     <strong><i class="fa fa-check-circle"></i> Success!</strong> {{ success | safe }} 
     <a href="#" class='close' data-dismiss="alert" aria-label="close"><i class='fa fa-times'></i></a> 
    </div> 
{% endfor %}