2

Express パスに基本認証を追加しようとしています。ユーザー/パスの組み合わせが正しいかどうかを確認するために、MongoDB データベースのコレクション ユーザーモデルを読み取りました。これが私のコードです:

サーバー.js

var normal = express.basicAuth(normalAuth);

app.get('path', normal, function(req, res){etc.});

function normalAuth(user, pass) {
  var mongo = require('./database/userManager');
  var result = false;
  mongo.start(mongo.list(function(err, data) {
      if(err) { throw err; }
      else {
        console.log('Getting list from db...');
        for(var i in data) {
          console.log('Getting details from db...');
          if(user == data[i].name && pass == data[i].pass) {
            console.log('New connection : ' + user);
            result = true;
            break;
          }
          else {
            console.log('Failed connection : ' + user);
            result = false;
          }
        }
        console.log('OK');
      }
      mongo.mongoose.connection.close();
  }));
  return result;
}

userManager.js

var mongoose = require('mongoose');

var userModel = mongoose.connection.model('usermodel', new mongoose.Schema({
    name: String,
    pass: String,
    status: { type: Boolean, default: false }
}), 'usermodels');

function start(callback) {
  mongoose.connect('mongodb://localhost/derp', function(err) {
      if(err) { throw err; }
      else { 
        console.log('Connected to database ');
      }
  });
}

function list(callback) {
  userModel.find(callback); 
}

認証はほぼ機能し、データベースに接続して情報を取得します。コンソールに出力されます

"New connection : /*user connected*/". 

しかし、問題があります。私の関数 normalAuth は常に false を返すため、正しいユーザー/パスを持っていても、ページにアクセスできず、間違ったユーザー/パスを与えたかのように接続ウィンドウが表示されます。mongo.start(blabla) が終了する前にこの関数が結果を返すためだと思いますが、どうすればよいかわかりません。

ご協力ありがとうございました。

4

1 に答える 1

3

Node.js ではすべての IO 操作が非同期であるため、常に誤った結果が得られます。

説明させてください:関数を呼び出すとmongo.start(...)、Node.jsはIO操作であるため、それを別の操作キューに入れます。メイン操作キューをブロックしてはなりません。そのため、IO 操作は常に非同期です。mongo 関数が操作の別のキューに入れられた後、メインの操作キューは続行され、コード行に到達します: return false. そして、どの関数mongo.start(...)がそれを処理するかに関係なく、false を返します。

解決策は、コールバック関数を送信することです:

function normalAuth(user, pass, callbackResult) {
  var mongo = require('./database/userManager');      
  mongo.start(mongo.list(function(err, data) {
      if(err) { throw err; }
      else {
        console.log('Getting list from db...');
        for(var i in data) {
          console.log('Getting details from db...');
          if(user == data[i].name && pass == data[i].pass) {
            console.log('New connection : ' + user);
            // here you send true to callback function
            callbackResult(true);
            break;
          }
          else {
            console.log('Failed connection : ' + user);
            // here you send false to callback function
            callbackResult(false);
          }
        }
        console.log('OK');
      }
      mongo.mongoose.connection.close();
  }));
}

そして、この関数を次のように呼び出します。

normalAuth(user, pass, function(result) {
    if(result)
        console.log("Auth OK");
    else
        console.log("Auth Failed");
}

EDITexpress.basicAuth関数では、次のように呼び出されます:

app.use(express.basicAuth(function(user, pass, callback) {
    normalAuth(user, pass, function(result) {     
        callback(null /* error */, result);
    }
}));
于 2013-05-29T13:49:21.007 に答える