没有达到的功能

时间:2016-07-30 12:07:39

标签: javascript node.js

我正在努力获得登录服务原型,这是我正在开展的这个个人项目的服务器端部分的第一步。我尝试引用代码herehere,因为它出自Learning Node.js书(由Marc Wandschneider编写),已经出了三年,因此已经证明有效。

我的实际服务器代码可以在this StackOverflow link找到。我跳过了数据库部分,因为我有trouble getting it up,而是让我的./helpers/users.js看起来像:

exports.version = "0.0.1";

var async = require('async'),
    bcrypt = require('bcrypt');

var helpers = require('./helpers.js');

function User(id, email, displayName, password, deleted)
{
    this.userID = id;
    this.email = email;
    this.displayName = displayName;
    if (User.connectedToDatabase) this._password = password;
    else
    {
        bcrypt.genSalt(10, function (err, salt) {
            // this, for some reason, isn't getting called. Literally, I never see "I'm here"
            console.log("I'm here...");
            bcrypt.hash(password, salt, function (err, hash) { 
                if (!err)
                {
                    this._password = hash;
                    console.log("this._password == " + this._password);
                }
                else
                {
                    console.log("Error occurred: ");
                    console.log(err);
                }
            })
        });
    }
    //this._password = password;
    this.deleted = deleted;
}

User.connectedToDatabase = false;

User.prototype.userID = 0;
User.prototype.email = null;
User.prototype.displayName = null;
User.prototype._password = null;
User.prototype.deleted = false;

User.prototype.checkPassword = function (password, callback)
{
    bcrypt.compare(password, this._password, callback); // returns false
}
User.prototype.responseObject = function() {
    return {
        id: this.userID,
        email: this.email,
        displayName: this.displayName
    };
}

exports.login = function (req, res) {
    var dblessPrototype = true;
    // get email address from req.body, trim it and lowercase it
    var email = req.body.emailAddress ? 
        req.body.emailAddress.trim().toLowerCase() :
        "";
    // begin the login process
    async.waterfall([
        // prelimninary verification: make sure email,password are not empty, and that email is of valid format
        function(cb) 
        {
            // if no email address
            if (!email)
            {
                // send error via cb
                cb(helpers.missingData("email_address"));
            }
            // if '@' not found in email address
            else if (email.indexOf('@') == -1)
            {
                // then email address is invalid
                cb(helpers.invalidData("email_address"));
            }
            // if password is missing from req.body
            else if (!req.body.password)
            {
                // tell next function about that
                cb(helpers.missingData("password"));
            }
            // we are ready to move on otherwise
            else cb(null);
        },
        // TODO: lookup by email address
        // check the password
        function (userData, cb)
        {
            var u;
            if (dblessPrototype)
            {
                u = new User(0, 
                    "admin@mikewarren.me",
                    "SampleAdmin",
                    "Sample0x50617373");
            }
            else 
            {
                u = new User(userData);
            }
            console.log("u._password == " + u._password);
            console.log("req.body.password == " + req.body.password);
            u.checkPassword(req.body.password, cb);
        },
        // time to set status of authenticiation
        function (authOK, cb)
        {
            console.log("authOK == " + authOK);
            if (!authOK)
            {
                cb(helpers.authFailed());
                return;
            }

            // set status of authenticiation in req.session
            req.session.loggedIn = true;
            req.session.emailAddress = req.body.emailAddress;
            req.session.loggedInTime = new Date();
        }
    ],
    function (err, results)
    {
        if (err)
        {
            console.log(JSON.stringify(err, null, '\t'));
            if (err.code != "already_logged_in")
            {
                helpers.sendFailure(res, err);
                console.log("Already logged in...");
            }
        }
        else
        {
            helpers.sendSuccess(res, { loggedIn: true });
            console.log("Log in successful...");
        }
    });

}

在检查密码时,u._password为空(它永远不会被设置,这意味着不会调用异步bcrypt.genSalt()代码。此外,数组中的最后一个函数都没有是async.waterfall()的第一个参数,也不是调用async.waterfall()的最后一个参数的函数。

为什么不调用这些函数,我该怎么办呢?

编辑:我通过替换

使异步密码加密同步
bcrypt.genSalt(10, function (err, salt) {
        // this, for some reason, isn't getting called. Literally, I never see "I'm here"
        console.log("I'm here...");
        bcrypt.hash(password, salt, function (err, hash) { 
            if (!err)
            {
                this._password = hash;
                console.log("this._password == " + this._password);
            }
            else
            {
                console.log("Error occurred: ");
                console.log(err);
            }
        })
    });

this._password = bcrypt.hashSync(password, bcrypt.genSaltSync(10));

它到达密码比较部分,挂起一段时间,然后到数组的下一个(最后一个)元素,而不向控制台打印任何内容。好像该元素被跳过了。

1 个答案:

答案 0 :(得分:1)

下载完整的应用程序并在家中乱搞后,

编辑

我将代码更改为包含setTimeout方法,并在User函数中强制执行this上下文。在我自己的机器上运行我从git repo下载的所有代码,我得到了用户通过认证的程度,应用程序查找不存在的index.html。因此身份验证正常运行!

在继续之前,代码不会等待salt和hash完成。如果你正在写一个数据库,你可以这样做' pre'保存并使用承诺。但是现在这将给你一个解决方法。

function (cb, userData)
    {
        var u;
        if (dblessPrototype)
        {
          var authOK;
            u = new User(0,
                "admin@mikewarren.me",
                "SampleAdmin",
                "Sample0x50617373");
                setTimeout(function () {
                  console.log("u._password == " + u._password);
                  console.log("req.body.password == " + req.body.password);
                  console.log(u)
                  u.checkPassword(req.body.password, function(err, res) {
                    if (err) {
                      console.log(err)
                    } else {
                      console.log(res)
                      // USER AUTHENTICATED
                      cb(null, true)
                    }
                    return res;
                  });
                }, 1000)
        }
        else
        {
            u = new User(userData);
    }
}

this分配给User对象生成器中的self

function User(id, email, displayName, password, deleted)
{
    this.userID = id;
    this.email = email;
    this.displayName = displayName;
    var self = this
    if (User.connectedToDatabase) this._password = password;
    else
    {
        bcrypt.genSalt(10, function (err, salt) {
            // this, for some reason, isn't getting called. Literally, I never see "I'm here"
            console.log("I'm here...");
            bcrypt.hash(password, salt, function (err, hash) {
                if (!err)
                {
                    self._password = hash;
                    console.log("this._password == " + self._password);
                }
                else
                {
                    console.log("Error occurred: ");
                    console.log(err);
                }
            })
        });
    }
    // this._password = password;
    this.deleted = deleted;
}

我应该补充一点,使用setTimeout不是推荐的方法,而是一种证明问题的方法。理想情况下,这应该使用回调,承诺或生成器来完成。