【问题标题】:NodeJS Express: How to interrupt the routing from outside the middleware/router?NodeJS Express:如何从中间件/路由器外部中断路由?
【发布时间】:2016-04-07 23:35:34
【问题描述】:

我实现了一个非常简单的中间件来检查用户的权限:

app.js

...
var security = require('./lib/security');
app.use(security.init);
...

lib/security.js

var session;
var request;
var response;

function init(req, res, next) {
  request = req;
  response = res;
  session = req.session;
  next();
}

function adminRequired(){
  if (!isAdmin()){
    response.redirect('/login');
    response.end();
    return true;
  }
  return false;
}
...

我发现中断流程的最佳方法如下:

routes/mycontroller.js

router.get('/', function(req, res, next) {
  if(security.adminRequiredHtml()){return;} // now it actually interrupt the execution
  res.render('admin',{});
  res.end();
});

但是,我想这样使用它:

routes/mycontroller.js

router.get('/', function(req, res, next) {
  security.adminRequiredHtml(); // <- interrupt the request
  res.render('admin',{});
  res.end();
});

它正确执行了重定向,但执行仍在继续:(
我已经尝试了一些解决方案,但它并没有真正起作用:
response.end() -> 关闭输出但继续执行
process.end() -> 它太激进了,终止执行但它也会杀死服务器:(

我一直在考虑使用 throw,但我不知道在哪里捕获它并让它优雅地终止(没有堆栈跟踪)

【问题讨论】:

  • 它不优雅,可能会导致混淆(并因此导致安全流程),因为浏览器上的结果是正确的,但执行仍在继续。

标签: node.js express terminate


【解决方案1】:

您可以创建一个受保护的自定义路由器并将您的安全路由添加到该路由器:

var secureRouter = express.Router();
// every request on this router goes throug this
secureRouter.use('*', function (req, res, next) {
  if(isAdmin()) next();
  // if you don't call next() you interrupt the request automaticly
  res.end();
});

// protected routes
secureRouter.get('/user', function(req, res){/* whatever */});
secureRouter.post('/user', function(req, res){/* whatever */});

app.use(secureRouter);

// not protected
app.get('/api', function(req, res){/* whatever */});

Express doc for using middlewares

【讨论】:

  • 我希望能够直接在控制器方法中使用,问题是如何优雅地中断路由。
  • 只是不要调用 next() 并且路由将在您当前的处理程序中结束。
  • Hem,我希望能够像使用“注释”一样使用它,这样我可以轻松保护单个方法或只是“放置”而不是“获取”网址
  • 好的,我得到了你想要的,但是为什么不将所有受保护的路由分组到“/admin/..”下呢?
  • 因为管理员这很容易,但是对于 /api/ 我希望能够“通过方法”控制,所以我可以允许 GET 但阻止 POST
【解决方案2】:

我认为您实际上是在寻找中间件。

function myMiddleware (req, req, next) {
   if (!isAdmin()) {
       res.redirect('/login');
       res.end();
   } else {
      //Proceed!
      next()
   }
}

router.get('/', myMiddleware, function(req, res, next) {
  res.render('admin',{});
  res.end();
});

您可以根据需要链接任意数量的逻辑来处理您需要的任何逻辑。如果您应该继续前进,请务必致电 next()!

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2015-11-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-09
    • 2013-06-18
    • 1970-01-01
    • 2017-03-08
    相关资源
    最近更新 更多