我正在尝试向基于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()。因此我很惊讶地看到第3个处理程序('*')也被调用了! 另一个惊喜是传递给第三个处理程序的响应('res')与传递给第一个处理程序的响应不同。 (如果我从第一个处理程序调用next(),那么将调用第二个处理程序,并使用相同的响应对象。)
现在我的真实场景:我想以全局方式处理请求并验证身份验证。但是,某些路由应该仍可供未经身份验证的用户使用。我的解决方案基于Zikes' answer。 我首先选择了“免费”路径。然后我为所有('*')包含了一个路由处理程序。如果用户通过身份验证,则会调用next(),否则调用next(错误)。以下是所有“限制”路线。最后,我自己的错误处理程序使用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');
});
这很有效,阻止访问'/ members'。但是,它有错误:即使访问非限制路径('/'),也会发生身份验证检查和错误处理。发送预期的响应后,错误处理程序尝试发送401错误响应。后者不会被发送,但代码不应该运行。
此外,此机制的一个副作用是未经身份验证的用户对不存在的页面会收到401错误。在某些情况下,我可能想要返回404。但现在我只是推动它......
我有两个问题:
答案 0 :(得分:2)
对于第一个问题,我的猜测是浏览器正在发送多个请求。
例如,当您浏览http://localhost:3000/
Chrome时,Chrome也会请求http://localhost:3000/favicon.ico
您可以使用以下内容打印正在捕获的请求:
app.get('*', function (req, res) {
console.log('this is reached');
console.log('url ' + req.url );
});
答案 1 :(得分: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);
答案 2 :(得分: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.');
})
所有处理的错误都应该具有状态。