Express用户认证中间件,它应该做多少?

Express user authentication middleware, how much should it do?

我正在尝试学习 Express 会话和身份验证处理。

例如:

app.post('/login', authCredentials, function(req, res) {
   console.log("second")
});

function authCredentials(req, res, next) {
  //this happens first
  console.log(req.body) // => { username: etc, password: etc }
  next(); 
}

我的问题是我的 authCredentials 函数应该做多少? 例如,如果凭证是正确的,我可以做类似的事情 res.redirect('/index')。但是,一旦我这样做了,第二个功能有什么用呢?

其他问题:

  1. 我将如何处理无效凭据?
  2. 如果我根据凭据使 authCredentials 只是 return truefalse,这不会破坏中间件流程,因为它永远不会调用 next()?
  3. 是否可以在之后的匿名回调中访问authCredentials中的任何内容?基本上在function(req, res) { }?

您想将 authCredentials 中间件添加到每个需要身份验证的端点。 app.post('/login') 通常不需要任何内容​​,因为您首先要访问此端点以实际获取凭据。

当凭据为 correct/valid 时,您只需调用 next(),工作流将跳转到下一个中​​间件或实际终点。如果出现错误,请使用 next(new Error('could not authenticate'); 等错误对象调用 next()。将错误路由添加到您的常规路由,错误将在那里处理:

app.use(function(err, req, res, next) {
    res.render('error', err);
});
  1. 现在应该回答了。
  2. 中间件没有return值。它要么调用 next(),要么通过调用 res.send().
  3. 以不同方式结束进程
  4. 有多种方法可以将变量从一个中间件传递到另一个中间件。最常见的可能是将所需的值附加到 req 参数。

authenticate是下例中的异步函数:

function authCredentials(req, res, next) {
    authenticate(req.body, function(err, user) {
        if (err) {
            return next(err);
        }
        req.user = user;
        next();
    });
}

答案取决于您的身份验证策略,即您是否使用会话标识符、访问令牌等

无论哪种情况,我都建议您从身份验证中分离出凭据交换(又名登录)。

function usernamePasswordExchange(req,res,next){
  var username = req.body.username;
  var password = req.body.password;

  callToAuthService(username,password,function(err,user){
    if(err){
      next(err); // bad password, user doesn’t exist, etc
    }else{
      /*
        this part depends on your application.  do you use
        sessions or access tokens?  you need to send the user
        something that they can use for authentication on
        subsequent requests
      */
      res.end(/* send something */);
    }
  });
}

function authenticate(req,res,next){
  /*
    read the cookie, access token, etc.
    verify that it is legit and then find
    the user that it’s associated with
  */
  validateRequestAndGetUser(req,function(err,user){
    if(err){
      next(err); // session expired, tampered, revoked
    }else{
      req.user = user;
      next();
    }
  });
}

app.post('/login',usernamePasswordExchange);

app.get('/protected-resource',authenticate,function(req,res,next){
  /*
    If we are here we know the user is authenticated and we
    can know who the user is by referencing req.user
  */
});

免责声明:我在 Stormpath 工作,我们花了很多时间写作 身份验证代码 :) 我刚刚编写了我们最新的库,stormpath-sdk-express, 具体实现了我的建议