【问题标题】:Express user authentication middleware, how much should it do?Express用户认证中间件,应该做多少?
【发布时间】:2015-01-30 00:31:50
【问题描述】:

我正在尝试学习 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 只是根据凭据返回truefalse,这不会破坏中间件流程,因为它永远不会调用next()
  3. 是否可以在之后的匿名回调中访问authCredentials 中的任何内容?基本上在function(req, res) { }?

【问题讨论】:

    标签: javascript express middleware


    【解决方案1】:

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

    在任何一种情况下,我都建议您从身份验证中取消凭据交换(也称为登录)。

    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, 其中有我的建议的具体实施

    【讨论】:

      【解决方案2】:

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

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

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

      authenticate 在下面的例子中是一个异步函数:

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

      【讨论】:

      • 所以澄清一下,您使用app.use(function(err, req, res, next) { res.render('error', err); }); 的第一个示例只是为了演示一种处理错误参数的方法,对吧?在您的第二个示例return next(err); 中,它正在返回下一个中间件函数?
      • 错误处理中间件需要 4 个参数,而不是通常的 3 个。如果您使用参数调用 next,则会自动调用错误中间件。如果您有不同的错误处理程序,它们的调用顺序与使用app.use 定义的顺序相同。欲了解更多信息,请点击此链接:expressjs.com/guide/error-handling.html
      • 好的,调用next(err)会自动发现中间件出错。不过,我们为什么要return next(err)?我猜authenticate 函数接收具有凭据的req.body,对其进行检查,然后调用回调,但这就是我对return next(err); 发生的事情感到困惑的地方
      • return 只是阻止整个函数在此处执行的一个小技巧。当出现错误时,我们不想继续req.user = user; 等等。当然,您可以将该部分包装在 else 语句中并省略 return。这只是为了更好的可读性。
      • 哦,另外,我忘记了我为什么不应该在app.post('/login') 进行身份验证而感到困惑。我的逻辑是,该特定路由仅在到该端点的 POST 上被激活。 req.body 何时会将用户凭据发送到端点?
      猜你喜欢
      • 1970-01-01
      • 2016-10-23
      • 1970-01-01
      • 1970-01-01
      • 2023-04-05
      • 2012-06-07
      • 1970-01-01
      • 2015-07-16
      • 2010-09-22
      相关资源
      最近更新 更多