【问题标题】:expressjs- injecting middleware to routes failedexpressjs-向路由注入中间件失败
【发布时间】:2017-12-17 19:10:20
【问题描述】:

我有多个路线页面。我们称它们为父路由(index.js)和子路由(child1.js、child2.js)。所有这些页面都指定了多条路线。其中一些需要受到保护,而另一些则最好不受保护。

在 JSON Web 令牌和 jsonwebtoken 包的帮助下,我创建了一个中间件,用于检查用户是否可以访问特定路由。用户只有在传递了有效的 json 令牌时才能访问它们。这适用于受保护的路由。 对于不受保护的路由,就不需要这样的东西了。

我将中间件保存在单独的页面中,并使用 module.exports 将其导出到路由页面,然后将其注入受保护的路由中。

但它不起作用。我尝试使用 POSTman 客户端访问受保护的路由,但从未发送过请求。加载器微调器显示。

这是我的代码:

auth-middleware.js

module.exports = function () {
    return function (req, res, next) {
        // check header or url parameters or post parameters for token
        var token = req.body.token || req.query.token || req.headers['x-access-token'];

        // decode token
        if (token) {
            // verifies secret and checks exp
            jwt.verify(token, config.secret, function (err, decoded) {
                if (err) {
                    return res.json({ success: false, message: 'Failed to authenticate token.' });
                } else {
                    // if everything is good, save to request for use in other routes
                    req.decoded = decoded;
                    next();
                }
            });
        }
        else {
            // if there is no token
            // return an error
            return res.status(403).send({
                success: false,
                message: 'No token provided.'
            });
        }
    }
}

我的父路由:index.js

var router = require('express').Router();

var protected = require('./auth-middleware')();

var childRoute1 = require('./child1');
var childRoute2 = require('./child2');
router.use('/child1', childRoute1);
router.use('/child2', childRoute2);

//unprotected parent route
router.get('/', function (req, res, next) {
  res.json('Unprotected route 1!');
});

//unprotected parent route
router.get('/albums/what',protected, function (req, res, next) {
  res.json('album!');
});

router.route('/login').post(User.loginUser);

module.exports = router;

我的孩子路线 1:child1.js

var child1Router = require('express').Router();
var protected = require('./auth-middleware')();
var ChildC = require('../controllers/childController');

child1Router.route('/all',protected).get(ChildC.fetchAllChildData); //protected
child1Router.route('/my').get(ChildC.fetchMyChildData); //unprotected

module.exports = child1Router;

child2 类似于 child1。所以我不包括它。

更新

我已经在 app.js 文件(主文件)中包含了正文解析器

const express = require('express');
var bodyParser = require('body-parser'); 
app = express();

var routes = require('./routes/index');
var port = process.env.PORT || 3000; //set our port

//configure body parser
app.use(bodyParser.urlencoded({ extended: true }));
app.use(bodyParser.json());

app.use('/api', routes);
app.use(function (req, res) {
  res.status(404).send({ url: req.originalUrl + ' not found' })
});

app.listen(port);
console.log('Magic happens on port ' + port);

module.exports = app;

【问题讨论】:

  • index.js 中的正文解析器在哪里。如何在不解析请求的情况下从 req.body 或 req.query 获取令牌。body-parser 必须存在。
  • 你如何在邮递员中发送请求?正如@VaibhavPatil 指出的那样,您没有显示body-parser,因此req.body.token 永远不会存在,因为它仅在您安装中间件以解析请求正文并将结果放入req.body 时才会填充。 req.query.token 或 req.headers['x-access-token'] 不需要 body-parser,因为它们在普通 Express 中可用。
  • @john 您是否没有将路由器安装到应用程序。写这个 var app = express();并在 index.js app.use("/", router); 的末尾
  • @Vaibhav Patil 我已经在 app.js 文件中包含 bodyparser 并安装了路由。请检查更新的代码。
  • @JohnDoe 导入中间件的时候不要执行,直接添加到路由中就可以了

标签: node.js express


【解决方案1】:

您可以使用verify 方法将中间件导出为对象,如下所示:

auth-middleware.js

module.exports = {
    verify: function (req, res, next) {
        // check header or url parameters or post parameters for token
        var token = req.body.token || req.query.token || req.headers['x-access-token'];

        // decode token
        if (token) {
            // verifies secret and checks exp
            jwt.verify(token, config.secret, function (err, decoded) {
                if (err) {
                    return res.json({ success: false, message: 'Failed to authenticate token.' });
                } else {
                    // if everything is good, save to request for use in other routes
                    req.decoded = decoded;
                    next();
                }
            });
        }
        else {
            // if there is no token
            // return an error
            return res.status(403).send({
                success: false,
                message: 'No token provided.'
            });
        }
    }
}

您现在可以要求var authMiddleware = require('../auth-middleware');

index.js

var router = require('express').Router();
var authMiddleware = require('./auth-middleware');

var childRoute1 = require('./child1');
var childRoute2 = require('./child2');
router.use('/child1', childRoute1);
router.use('/child2', childRoute2);

// unprotected parent route
router.get('/', function (req, res, next) {
  res.json('Unprotected route 1!');
});

// protected parent route
router.get('/albums/what', authMiddleware.verify, function (req, res, next) {
  res.json('album!');
});

router.route('/login').post(User.loginUser);

module.exports = router;

或者您可以将受保护的路由放在router.user 下,如下所示:

 router.use('/child1', childRoute1);
 router.use('/child2', childRoute2);

 // unprotected parent route
 router.get('/', function (req, res, next) {
   res.json('Unprotected route 1!');
 });
 router.route('/login').post(User.loginUser);

 // route middleware to verify token
 router.use(authMiddleware.verify);

 // protected parent route
 router.get('/albums/what', function (req, res, next) {
   res.json('album!');
 });

【讨论】:

  • 导出的是一个返回中间件函数的函数,所以实际上需要调用它。
  • @robertklep 注意。
  • @akinjide 我尝试了您提供的解决方案。但我收到以下错误:错误:未指定默认引擎且未提供扩展名。
  • 我正在使用 ExpressJS 创建一个 api。所以我想不需要意见。
  • @JohnDoe 是的!如果你在做服务器端渲染,你只需要views。
猜你喜欢
  • 1970-01-01
  • 2023-01-21
  • 1970-01-01
  • 1970-01-01
  • 2021-09-06
  • 2016-05-31
  • 1970-01-01
  • 1970-01-01
  • 2021-11-23
相关资源
最近更新 更多