使用Express.JS中的dynamicURL进行HTTP身份validation

我的Express 3.0应用程序中有一条路线,如下所示:

app.post('/:app/find', auth, function(req, res){ 

我希望使用HTTP授权进行限制。 我的authfunction看起来像这样:

 var auth = express.basicAuth(function(user, pass, callback){ callback(null, user === 'user' && pass === 'pass'); }); 

我希望auth函数根据URL中的req.params.app进行数据库查找,并相应地对用户进行身份validation。 问题是,我不确定如何访问它,因为app.post中定义的函数在auth运行app.post没有被调用。 我在哪里可以得到它? 是否有一个不同的HTTP身份validation我应该使用的实现?

express.basicAuth (我也看了一些提供类似function的其他模块,但是他们似乎也不会传递req到authentication函数),但是你可以创build一个中间件来实例化它对于您要validation的每个请求:

 var express = require('express'); var app = express(); var basicAuth = express.basicAuth; var auth = function(req, res, next) { ...here you can access 'req'... basicAuth(function(user, pass, callback) { ...here you can use variables set in the block above... callback(null, user === 'user' && pass === 'pass'); })(req, res, next); }; app.get('/', auth, function(req, res) { res.send('authenticated!'); }); app.listen(3012); 

我在StackOverflow上发现了一个类似的问题 ,但是在获得提供的答案时遇到了一些麻烦。 我把它转换成中间件,使它更好地适应:

 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从未设置。 我被困住了,直到我遇到了这个要点 ,这暗示了即使客户正在发送授权标题,我仍然不得不要求他们。 所以我补充说:

 if(req.auth){ // Do things }else{ res.setHeader('WWW-Authenticate', 'Basic realm="Secure Area"'); res.statusCode = 401; res.end("NO_CREDENTIALS"); } 

然后,我开始在req.auth看到数据,但是对象具有“username”和“password”属性,而不是我指定的“user”和“pass”属性。 多了一点点后,我发现…那些是由快递自动! 无论如何,似乎是这样。 我做了一个没有任何中间件或其他装饰的新应用程序,并得到了相同的结果,只要我发送了WWW-Authenticate标头。 这使得我的includeAuth中间件function无用。 有了我的新知识,我现在可以使用以下方法在客户端尝试进行身份validation时向客户端提供特定的错误消息:

 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}); }); }); 

然而,我要给罗伯特正确的答案,因为他的解决scheme不仅工作完美,而且使用更less(更简单)的代码到达那里,并且会更好地适应别人的项目,如果他们碰到这个问题。