如何访问basicAuth内部的快速路由

我的NodeJS服务器,使用express,有一堆条目来指定各种路由:

app.post('list_streams.json', auth, stream_handler.list_streams); app.post('add_stream.json', auth, stream_handler.add_stream); app.post('delete_stream.json', auth, stream_handler.delete_stream); etc... 

auth中间件是这样写的:

 var auth = express.basicAuth(function(user, pass, callback) { user_handler.authenticate_user(user, pass, callback); }); 

在user_handler.authenticate_user()函数内部,执行数据库访问来validation用户。 我想添加一些统计信息并跟踪特定用户执行的每个访问。 我想在authenticate_user()函数内部这样做,因为这是为用户logging访问数据库的地方,我可以使用相同的访问来更新用户logging中的统计信息,但是我需要以某种方式传递对authenticate_user()指定已执行的访问types的额外参数; 要么是路由本身,要么是标识正被访问路由的标记。 而我无法弄清楚如何做到这一点。 “req”在authenticate_user()函数内不可用。

谢谢你,加里

我不确定你需要什么,可以很容易地从你的authenticate_user函数完成,因为在任何用户的第一次访问中,每个会话只调用一次。

logging每个用户的所有访问权限的最好方法是创build一个新的中间件function,如本文末尾所述。

但是,假设你只是想logging用户身份validation,解决你的问题的一种方法是用你自己的版本replaceexpress.basicAuth,将callback函数绑定到express req对象,如下所示:

 var util=require('util'), express=require('express'), app=express(), auth=basicAuth(function(username,password,next){ console.log('auth has access to req as "this": %s',util.inspect(this)); }); app.get('/',auth,function(req,res){ console.log('in request for "/", req is: %s',util.inspect(req)); res.send('SUCCESS'); }); app.listen(4000,function(){ console.log('running'); }); // Replacement for connect.basicAuth (as used by express) // lifted from https://github.com/expressjs/basic-auth-connect function unauthorized(res, realm) { // required by basicAuth res.statusCode = 401; res.setHeader('WWW-Authenticate', 'Basic realm="' + realm + '"'); res.end('Unauthorized'); } function error(code, msg){ // required by basicAuth var err = new Error(msg || http.STATUS_CODES[code]); err.status = code; return err; } // replacement basic auth which binds the callback to the "req" object function basicAuth(callback, realm) { var username, password; // user / pass strings if ('string' == typeof callback) { username = callback; password = realm; if ('string' != typeof password) throw new Error('password argument required'); realm = arguments[2]; callback = function(user, pass){ return user == username && pass == password; } } realm = realm || 'Authorization Required'; return function(req, res, next) { var authorization = req.headers.authorization; // 20140601 RR - !!NOTE!! bind callback to req callback=callback.bind(req); if (req.user) return next(); if (!authorization) return unauthorized(res, realm); var parts = authorization.split(' '); if (parts.length !== 2) return next(error(400)); var scheme = parts[0] , credentials = new Buffer(parts[1], 'base64').toString() , index = credentials.indexOf(':'); if ('Basic' != scheme || index < 0) return next(error(400)); var user = credentials.slice(0, index) , pass = credentials.slice(index + 1); // async if (callback.length >= 3) { callback(user, pass, function(err, user){ if (err || !user) return unauthorized(res, realm); req.user = req.remoteUser = user; next(); }); // sync } else { if (callback(user, pass)) { req.user = req.remoteUser = user; next(); } else { unauthorized(res, realm); } } } } 

如果你看看标有“!! !!”的行, 在上面,你会看到你传递给新的basicAuth函数的callback已经绑定表示' req请求对象,这使得它的想法是对请求的引用。

现在,您只需引用this.url即可获取原始请求URL并将其logging下来。

如上所述,需要注意的一点是, auth的callback只会被调用来authentication用户一次。

后续请求已经设置了req.user HTTP头部variables,所以请求被允许通过而不调用authenticationcallback。

这就是为什么logging特定用户所有交互的最好方法是在调用auth之后添加自己的中间件,例如:

 function logUser(req,res,next){ // since this middleware is called AFTER auth, the user is already authorized. log.info('user "'+req.user+'" called url:'+req.url); next(); // pass control to the next stage in fulfilling the request } app.get('/',auth,logUser,function(req,res){ ... });