在全局范围内路由之前拦截NodeJS(Express)上的标头

时间:2018-02-25 19:29:18

标签: node.js express

我的server.js

上有这样的代码
var session = {
    v1: require('./routes/v1/session')
}
app.post('/v1/session/login', session.v1.login);
app.get('/v1/session/logout/:uuid', session.v1.logout);

var modify = {
   v1: require('./routes/v1/modify')
}
app.put('/v1/modify/:uuid/password', modify.v1.password);
app.put('/v1/modify/:uuid/mobile', modify.v1.mobile);
app.put('/v1/modify/:uuid/email', modify.v1.email);

以上所有情况我发送一个带有令牌的Authorization标头,除了登录,因为您将在登录后收到令牌。

因此,在我的所有路由中,我需要调用例程来验证令牌,然后执行操作。像这样:

exports.logout = function (req, res) {
   var auth = req.headers.authorization;
   global.utils.validateToken(auth).then(function(uuid) {  
       // Code here
   }
}

但我相信有更好的方法可以做到这一点。比如在调用路由器之前对每个服务器请求执行授权检查。

这样的事情可能吗?如果是:我可以定义例外(例如......如果是登录,我不需要检查授权)?

谢谢!

1 个答案:

答案 0 :(得分:1)

有多种方法可以这样做,我说明了三种方法,你可以随心所欲。

基本上,你需要制作一个登录时不应该调用的中间件。

你要做的是,制作一个如下所示的中间件:

var middleware = {
  authTokenValidator = function(req, res, next) {
    var auth = req.headers.authorization;
    global.utils.validateToken(auth).then(function(uuid) {
      // Token Valid Code here
      next();
    }).catch(function(err) {
      // Token failure handling code here
      res.status(401).json(err);
    })
  }
}

现在你可以用两种方式使用这个中间件: 首先是在需要的地方使用中间件,如下所示:

var session = {
    v1: require('./routes/v1/session')
}
// Skipped for login
app.post('/v1/session/login', session.v1.login);
app.get('/v1/session/logout/:uuid', middleware.authTokenValidator, session.v1.logout);

var modify = {
   v1: require('./routes/v1/modify')
}
app.put('/v1/modify/:uuid/password', middleware.authTokenValidator, modify.v1.password);
app.put('/v1/modify/:uuid/mobile', middleware.authTokenValidator, modify.v1.mobile);
app.put('/v1/modify/:uuid/email', middleware.authTokenValidator, modify.v1.email);

所以基本上使用下一个函数你可以传递任意数量的函数作为中间件并调用下一个中间件函数。

第二种方法是全局传递中间件并处理登录URL等异常: 定义中间件上面不应该通过中间件的所有路由以及中间件下面的其他路由,如下面的代码所示:

var session = {
    v1: require('./routes/v1/session')
}
// Skipped for login
app.post('/v1/session/login', session.v1.login);

// All the requests except the above path will go throgh this middleware
app.use(middleware.authTokenValidator)

app.get('/v1/session/logout/:uuid', session.v1.logout);

var modify = {
   v1: require('./routes/v1/modify')
}
app.put('/v1/modify/:uuid/password', modify.v1.password);
app.put('/v1/modify/:uuid/mobile', modify.v1.mobile);
app.put('/v1/modify/:uuid/email', modify.v1.email);

并且,第三种方法类似于第二种方法,但检查中间件中的请求路径并跳过它,这不是优选的...

var middleware = {
  authTokenValidator = function(req, res, next) {
    var no_validate_path = ['/v1/session/login']
    // Skipping the login path here
    if (no_validate_path.indexOf(req.path) >= 0) {
      next()
    } else {
      var auth = req.headers.authorization;
      global.utils.validateToken(auth).then(function(uuid) {
        // Token Valid Code here
        next();
      }).catch(function(err) {
        // Token failure handling code here
        res.status(401).json(err);
      })
    }

  }
}

您的路线代码为:

//Adding middleware for all the paths
app.use(middleware.authTokenValidator)

var session = {
  v1: require('./routes/v1/session')
}
app.post('/v1/session/login', session.v1.login);
app.get('/v1/session/logout/:uuid', session.v1.logout);
var modify = {
  v1: require('./routes/v1/modify')
}
app.put('/v1/modify/:uuid/password', modify.v1.password);
app.put('/v1/modify/:uuid/mobile', modify.v1.mobile);
app.put('/v1/modify/:uuid/email', modify.v1.email);

参考阅读有关中间件https://expressjs.com/en/guide/using-middleware.html

的内容