我发现这里a similar question在计算器上,但有一些麻烦提供工作答案。我把它转换到中间件,使之适合于更漂亮:
var includeAuth = function(req, res, next){
var header = req.header('authorization', false);
if(header){
var token = header.split(/\s+/).pop() || '';
if(token.length > 0){
var auth = new Buffer(token, 'base64').toString(),
parts = auth.split(/:/);
req.auth = {user: parts[0], pass: parts[1]};
}else
req.auth = false;
}else
req.auth = false;
next();
}
app.configure(function(){
app.use(includeAuth);
});
...但req.header.authorization
从未设置过。我被困住了,直到我遇到了this gist,这暗示了即使客户端发送授权标题,我仍然不得不请求它们。所以我说这一点:
if(req.auth){
// Do things
}else{
res.setHeader('WWW-Authenticate', 'Basic realm="Secure Area"');
res.statusCode = 401;
res.end("NO_CREDENTIALS");
}
然后我开始在req.auth
看到数据,但对象有属性“用户名”和“密码”,而不是“用户”和“通”为我所指定。经过多一点的探索后,我发现......这些都是由Express自动发出的!无论如何,看起来似乎如此。我做了一个没有任何中间件或其他装饰的新应用程序,并且获得了相同的结果,只要我发送了WWW-Authenticate标头即可。这使我的includeAuth
中间件功能无用。与我的新发现的知识,我现在可以使用下面提供具体的错误信息给客户,当他们尝试验证:
function verifyAuth(req, res, appName, callback){
if(req.auth){
db.apps.findOne({id: appName}, function(err, app){ // Call to MongoDB
if(!err && app){
if(app.user === req.auth.username && app.pass === req.auth.password)
callback(null, true);
else
callback("INVALID_CREDENTIALS", false);
}else
callback("NO_SUCH_APP", false);
});
}else{
res.setHeader('WWW-Authenticate', 'Basic realm="Secure Area"');
res.statusCode = 401;
res.end(JSON.stringify({success: false, error: "NO_CREDENTIALS"}));
callback(null, false);
}
}
app.post('/:app/find', function(req, res){
verifyAuth(req, res, req.params.app, function(err, allowed){
if(!err && allowed){
// Do some things
}else if(err)
res.send({success: false, error: err});
});
});
不过,我想给罗伯特正确的答案,因为他的解决方案不仅可以完美运行,而且可以使用更少(更简单)的代码来实现,并且可以更好地适应别人的项目,如果他们遇到了这个问题。