如何使用Express和PassportJS正确报告无效登录?

Ant*_*lad 4 mongoose node.js express passport.js

我已成功在我的Express/Mongoose网络应用程序中实现了本地护照,但我无法确定如何正确呈现失败的登录消息.

这是我的登录路线:

app.get('/login', function(req, res) {
   res.render('user/login', {
   });
});
Run Code Online (Sandbox Code Playgroud)

有了这样的路线我该怎么报告无效登录?如果登录成功,将写id/ usernamereq.user对象,但并不能帮助我的"GET /login"路线,因为如果成功,你会重定向到你想去的页面.

这意味着req.user将始终undefined在您GET登录页面时.

我希望能够写出一条消息,上面写着'哟,登录无效!' 当发生以下事情时:

  1. 用户不存在.
  2. 提供的密码不匹配,但用户已存在.

我可能希望根据发生的情况输出不同的消息.

当我实现LocalStrategy时,我使用了以下代码:

passport.use(new LocalStrategy({
    usernameField: 'email'
},
function(email, password, fn) {
  User.findOne({'login.email': email}, function(err, user) {
    // Error was thrown.
    if (err) {
      return fn(err);
    }

    // User does not exist.
    if (!user) {
      return fn(null, false);
    }

    // Passwords do not match.
    if (user.login.password != utility.encryptString(user.login.salt + password)) {
      return fn(null, false);
    }

    // Everything is good.
    return fn(null, user);
  });
}
));
Run Code Online (Sandbox Code Playgroud)

正如您所看到的,存在一些问题,但这就是PassportJS的作者如何设置他的应用程序.我们如何才能获得战略回归的内容?

就像它抛出错误一样,我甚至应该打电话来获取访问权限err

谢谢.

Jar*_*son 17

在最新版本的Passport中,我添加了对flash消息的支持,这使得您可以轻松地完成您的要求.

您现在可以提供第三个参数done,其中可以包含失败消息.例如:

if (user.login.password != utility.encryptString(user.login.salt + password)) {
  return fn(null, false, { message: 'yo, invalid login!' });
}
Run Code Online (Sandbox Code Playgroud)

然后,设置failureFlashtrue作为一个选项authenticate().

passport.authenticate('local', { successRedirect: '/',
                                 failureRedirect: '/login',
                                 failureFlash: true });
Run Code Online (Sandbox Code Playgroud)

在这种情况下,如果身份验证失败,则会在闪存中设置消息,以便在再次显示登录页面时进行渲染.

自定义回调也很好.内置选项使得完成常见任务变得更加简单.

另外,我很好奇:你提到样品有问题.您认为应该改进什么?我想让这些例子尽可能好.谢谢!

(有关详细信息,请参阅有关问题#12的此评论).


Wes*_*son 10

您可以使用自定义回调或中间件功能来获得更多控制权.有关示例,请参阅指南的" 身份验证"部分.

例如,自定义回调可能如下所示:

app.get('/login', function(req,res,next) {
    passport.authenticate('local', function(err,user) {
            if(!user) res.send('Sorry, you\'re not logged in correctly.');
            if(user) res.send('Skeet skeet!');
    })(req,res,next);
});
Run Code Online (Sandbox Code Playgroud)

或者,您可以始终重定向两个响应:

app.get('/login', 
    passport.authenticate('local', { successRedirect: '/winner',
                                     failureRedirect:'/loser' }));
Run Code Online (Sandbox Code Playgroud)

或者使用简单的中间件重定向故障:

app.get('/login', ensureAuthenticated,
    function(req,res) {
                // successful auth
                // do something for-the-win
    }
);

    // reusable middleware
    function ensureAuthenticated(req,res,next) {
        if(req.isAuthenticated()) {return next();}
        res.redirect('/login/again'); // if failed...
    }
Run Code Online (Sandbox Code Playgroud)