我正在尝试向基于 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。但现在我只是在推动它...
我有两个问题:
- 这种行为是错误吗?是否应该调用通用处理程序而不调用下一个?
- 什么是挂钩许多但不是所有路线的好解决方案,而不必单独标记它们?