2

我正在尝试向基于 Express 的服务器添加身份验证。我注意到路由的一些奇怪行为。

我已经将问题提炼为这个 Express 代码:

app.get('/', function (req, res) {
    console.log('this is reached first');
    res.send('Hello');
});

app.get('/', function (req, res) {
    console.log('this is not reached');
});

app.get('*', function (req, res) {
    console.log('this is reached');
});

在请求“/”时,调用第一个处理程序。它提供响应并且不调用 next()。因此,我很惊讶地看到第三个处理程序('*')也被调用了!另一个惊喜是传递给第三个处理程序的响应('res')与传递给第一个处理程序的响应不同。(如果我要从第一个处理程序调用 next() ,那么将调用第二个处理程序,并使用相同的响应对象。)

现在是我的真实场景:我想以全局方式处理请求并验证身份验证。但是,某些路由应该对未经身份验证的用户仍然可用。我的解决方案基于Zikes 的回答。我首先路由了“自由”路径。然后我为所有('*')添加了一个路由处理程序。如果用户通过身份验证,它将调用 next(),否则调用 next(err)。以下是所有“受限”路线。最后,我自己使用 app.use 的错误处理程序。它看起来像这样:

app.use(app.router);
app.use(function(err, req, res, next) {
    console.log('An error occurred: ' + err);
    res.send(401, 'Unauthorized');
});

app.get('/', function (req, res) {
    res.send('Hello all');
});

app.all('*', function (req, res, next) {
    if (req.user) {
        next(); // authorized
    } else {
        next(new Error('401')); // unauthorized
    }
});

app.get('/members', function (req, res) {
    res.send('Hello member');
});

这工作得很好,阻止了对“/成员”的访问。但是,它有一个错误:即使在访问非限制路径('/')时也会发生身份验证检查和错误处理。发送预期响应后,错误处理程序会尝试发送 401 错误响应。后者不会被发送,但代码不应运行。

此外,这种机制的副作用是未经身份验证的用户会收到不存在页面的 401 错误。在某些情况下,我可能想返回 404。但现在我只是在推动它...

我有两个问题:

  1. 这种行为是错误吗?是否应该调用通用处理程序而不调用下一个?
  2. 什么是挂钩许多但不是所有路线的好解决方案,而不必单独标记它们?
4

3 回答 3

2

对于第一个问题,我的猜测是浏览器发送了多个请求。

例如,当您浏览到http://localhost:3000/Chrome 时,还会请求http://localhost:3000/favicon.ico

您可以打印被捕获的请求,如下所示:

app.get('*', function (req, res) {
    console.log('this is reached');
    console.log('url ' + req.url );
});
于 2012-10-09T13:00:30.300 回答
1

首先,您在回家时可能有两个请求(favicon.ico)。用于app.use(express.logger('dev'))记录请求。此外,您可以尝试阻止该路径:

app.use('/favicon.ico', function(req, res) {
  console.log('FAVICON')
  res.send(404)
}

其次,你想处理你的错误。发送错误的好方法:

var err = new Error('this is my error message.')
err.status = 404 // You want to send a "Not Found" page
next(err)

app.use(function(err, req, res, next) {
  var status = err.status
  if (status === 404) res.send(404, 'Page not found.');
  else res.send(500, 'Something went wrong.');
})

所有处理的错误都应该有一个状态。

于 2012-10-10T06:09:39.010 回答
1
app.get('/', function(req, res, next) {
    console.log('this is reached first.');
    next();
}, function (req, res) {
    console.log('this is reached last.');
    res.send('Hello all');
});

我通常会这样构建它:

var auth = require('../modules/authenticate');

app.get('/', auth.requireLogin, routes.index.get);
app.delete('/items/:id', auth.requireLogin, auth.permission.item.delete, routes.item.delete);
于 2012-10-09T17:44:08.463 回答