使用Passport进行Node.js身份验证:如果字段丢失,如何刷新消息?

Mae*_*ole 12 javascript node.js passport.js

我正在使用passport.js,如果我的表单中的字段为空,我想要闪烁一条消息.但是我不知道怎么做,因为护照不会触发策略回调,如果缺少那些.我真的希望这个用例更清楚,我不想修改护照.我觉得有办法这样做,但我不知道在哪里!我试图使用route(app.post)的回调但它似乎没有按照我尝试的方式工作.

这是验证函数原型:

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);
  }
};
Run Code Online (Sandbox Code Playgroud)

这是我的策略:

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

    }));
Run Code Online (Sandbox Code Playgroud)

最后我的路线:

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");
    }));
Run Code Online (Sandbox Code Playgroud)

ves*_*sse 17

您不应该调用req.flash验证回调.相反,您应该返回文档中显示的消息.Passport会将消息返回到flash消息时failureFlash: true.

您修改后的验证回调:

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

    }));
Run Code Online (Sandbox Code Playgroud)

和路线:

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
}));
Run Code Online (Sandbox Code Playgroud)

编辑:

这是一个完整的例子:https://gist.github.com/vesse/9e23ff1810089bed4426


Kei*_*ith 5

这是一个老问题,但我找不到答案.希望这有助于其他人.


我认为文档在使用时有点不完整connect-flash.他们说:

注意:使用flash消息需要req.flash()函数.Express 2.x提供了此功能,但它已从Express 3.x中删除.建议使用connect-flash中间件在使用Express 3.x时提供此功能.

然而,没有提到在done()回调中使用req.flash .基于该scotch.io教程,你其实应该req.flash()正确的,在回调.这个对我有用.

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

你需要使用passReqToCallback当然.也一定failureFlash要设置为true.OP已经正确地做了这些.

现在您可以检查路线中的flash消息.请注意,connect-flash发送一组消息.如果他的模板期待一个字符串,这可能是OP的问题.

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

});
Run Code Online (Sandbox Code Playgroud)

如果页面上有多个登录消息,则传递整个req.flash('loginMessage')数组并在模板中迭代它.下面是使用nunjucks的示例.


专家提示:

如果您有许多带有Flash消息的路由,则可以始终将它们设置res.locals为中间件路由.这不会干扰其他当地人,比如title.这是我的实现,使用bootstrap警报.

在我的策略中:

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

在我的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'}); 
});
Run Code Online (Sandbox Code Playgroud)

在我的nunjucks基础模板中:

<!--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 %}
Run Code Online (Sandbox Code Playgroud)