我正在努力获得登录服务原型,这是我正在开展的这个个人项目的服务器端部分的第一步。我尝试引用代码here和here,因为它出自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));
它到达密码比较部分,挂起一段时间,然后到数组的下一个(最后一个)元素,而不向控制台打印任何内容。好像该元素被跳过了。
答案 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不是推荐的方法,而是一种证明问题的方法。理想情况下,这应该使用回调,承诺或生成器来完成。