node.js - 如何访问 basicAuth 内的快速路由

标签 node.js express

我的 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() 函数内,执行对数据库的访问以验证用户。我想添加一些统计数据并跟踪特定用户执行的每次访问。我想在authenticate_user()函数中执行此操作,因为这是访问用户记录的数据库的地方,我可以使用相同的访问权限来更新用户记录中的统计信息,但我需要以某种方式传递authenticate_user() 的额外参数指定所执行的访问类型;路由本身或标识正在访问的路由的某些标记。我不知道该怎么做。 “req”在authenticate_user()函数中不可用。

谢谢你, 加里

最佳答案

我不确定您需要什么可以通过您的authenticate_user函数轻松完成,因为它在任何用户第一次访问时每个 session 仅调用一次。

记录每个用户的所有访问的最佳方法是创建一个新的中间件函数,如本文末尾所述。

但是假设您只想记录用户身份验证,解决问题的一种方法是将express.basicAuth 替换为您自己的版本,该版本将回调函数绑定(bind)到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);
      }
    }
  }
}

如果您查看标有“!!NOTE!!”的行在上面,您将看到传递给新 basicAuth 函数的回调已绑定(bind)到 express 的 req 请求对象,这使得其 this 的概念成为对请求的引用。

现在您需要做的就是引用 this.url 来获取原始请求 URL 并记录它。

如上所述,需要注意的一件事是对 auth 的回调仅被调用以对用户进行一次身份验证。

后续请求已经设置了 req.user HTTP header 变量,因此允许请求通过,而无需调用身份验证回调。

这就是为什么记录特定用户的所有交互的最佳方法是在调用 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){
    ...
});

关于node.js - 如何访问 basicAuth 内的快速路由,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23976965/

相关文章:

node.js - 如何在 Redis 中实现条件弹出并发友好?

node.js - 特定路由的 Express ip 过滤器?

node.js - 在 next.js 应用程序上管理用户的全局状态

javascript - 如何根据来自 REST 调用的响应形成 json 数组?

javascript - 如何使用 Node 创建一个子进程作为特定用户?

SQL 查询为 SQLite 返回 JSON 中的嵌套对象数组

javascript - 如何访问 req.body 的特定部分(Node JS)

ember.js - 通过 HTTPS 的 Ember CLI 服务器

javascript - 为什么 Node.js 无法处理 Vue.js 的请求?

javascript - Mongoose "find"返回一个空数组