[英]Implement change password with Loopback
I am trying to implement the change password feature with Loopback's built-in method, It works fine, but it doesn't update the password with hash
instead it just saves a plain text in the db. 我正在尝试使用Loopback的内置方法实现更改密码功能,它工作正常,但它不会使用
hash
更新密码,而只是在数据库中保存纯文本。 I am using loopback-component-passport
npm package in this project. 我在这个项目中使用
loopback-component-passport
npm包。 I have searched many sites but I am unable to find the proper way to implement this feature. 我搜索了很多网站,但我无法找到实现此功能的正确方法。 Does anyone have idea how to do this?
有谁知道如何做到这一点?
//Change user's pasword
app.post('/change-password', function(req, res, next) {
var User = app.models.user;
if (!req.accessToken) return res.sendStatus(401);
//verify passwords match
if (!req.body.password || !req.body.confirmation ||
req.body.password !== req.body.confirmation) {
return res.sendStatus(400, new Error('Passwords do not match'));
}
User.findById(req.accessToken.userId, function(err, user) {
if (err) return res.sendStatus(404);
user.hasPassword(req.body.oldPassword, function(err, isMatch) {
if (!isMatch) {
return res.sendStatus(401);
} else {
user.updateAttribute('password', req.body.password, function(err, user) {
if (err) return res.sendStatus(404);
console.log('> password change request processed successfully');
res.status(200).json({msg: 'password change request processed successfully'});
});
}
});
});
});
Use built-in User.hashPassword
which seen in source code 使用源代码中看到的内置
User.hashPassword
//Hash the plain password
user.updateAttribute('password', User.hashPassword(req.body.password), function(err, user) {
...
});
This is actually a bug that was introduced with loopback-datasource-juggler 2.45.0. 这实际上是loopback-datasource-juggler 2.45.0引入的一个错误。 The password should be hashed by default.
密码应默认为哈希值。
https://github.com/strongloop/loopback-datasource-juggler/issues/844 https://github.com/strongloop/loopback-datasource-juggler/issues/844
https://github.com/strongloop/loopback/issues/2029 https://github.com/strongloop/loopback/issues/2029
So beware if you use user.hashpassword it may not work in a future version when this is fixed since it might hash an already-hashed pw if not done correctly, but there should already be a check for the length plus checking for $2$ or whatever the start bit is for hash values. 因此,请注意,如果您使用user.hashpassword,它可能无法在以后的版本中修复,因为它可能会散列已经散列的pw,如果没有正确完成,但应该已经检查了长度加上检查$ 2 $或无论起始位是否为哈希值。
Edit : Install 2.45.1 of loopback-datasource-juggler and it should be fixed. 编辑 :安装2.45.1的loopback-datasource-juggler,它应该是固定的。
Here is my "full" solution to implement a specific updatePassword remote method in a LoopBack / StrongLoop - IBM project. 这是我在LoopBack / StrongLoop - IBM项目中实现特定updatePassword远程方法的“完整”解决方案。 Please verify that the
loopback-datasource-juggler
package has a higher or equal version than 2.45.1 ( npm list loopback-datasource-juggler
). 请验证
loopback-datasource-juggler
包的版本是否高于或等于2.45.1( npm list loopback-datasource-juggler
)。 My user Model is called MyUserModel
and inherits from the built-in model User
: 我的用户模型名为
MyUserModel
并继承自内置模型User
:
"my-user-model.js" “我的用户,model.js”
module.exports = function (MyUserModel) {
...
MyUserModel.updatePassword = function (ctx, emailVerify, oldPassword, newPassword, cb) {
var newErrMsg, newErr;
try {
this.findOne({where: {id: ctx.req.accessToken.userId, email: emailVerify}}, function (err, user) {
if (err) {
cb(err);
} else if (!user) {
newErrMsg = "No match between provided current logged user and email";
newErr = new Error(newErrMsg);
newErr.statusCode = 401;
newErr.code = 'LOGIN_FAILED_EMAIL';
cb(newErr);
} else {
user.hasPassword(oldPassword, function (err, isMatch) {
if (isMatch) {
// TODO ...further verifications should be done here (e.g. non-empty new password, complex enough password etc.)...
user.updateAttributes({'password': newPassword}, function (err, instance) {
if (err) {
cb(err);
} else {
cb(null, true);
}
});
} else {
newErrMsg = 'User specified wrong current password !';
newErr = new Error(newErrMsg);
newErr.statusCode = 401;
newErr.code = 'LOGIN_FAILED_PWD';
return cb(newErr);
}
});
}
});
} catch (err) {
logger.error(err);
cb(err);
}
};
MyUserModel.remoteMethod(
'updatePassword',
{
description: "Allows a logged user to change his/her password.",
http: {verb: 'put'},
accepts: [
{arg: 'ctx', type: 'object', http: {source: 'context'}},
{arg: 'emailVerify', type: 'string', required: true, description: "The user email, just for verification"},
{arg: 'oldPassword', type: 'string', required: true, description: "The user old password"},
{arg: 'newPassword', type: 'string', required: true, description: "The user NEW password"}
],
returns: {arg: 'passwordChange', type: 'boolean'}
}
);
...
};
"my-user-model.json" “我的用户,model.json”
{
"name": "MyUserModel",
"base": "User",
...
"acls": [
...
{
"comment":"allow authenticated users to change their password",
"accessType": "EXECUTE",
"property":"updatePassword",
"principalType": "ROLE",
"principalId": "$authenticated",
"permission": "ALLOW"
}
...
],
...
}
NB: The same functionality can be performed using a PUT request on MyUserModel and just specifying { "password":"...newpassword..."} in the body.
注意:可以使用MyUserModel上的PUT请求执行相同的功能,只需在正文中指定{“password”:“... newpassword ...”}即可。 But it probably is more convenient to have a specific remote method than this trick in order to enforce security policy on the new password.
但是为了对新密码实施安全策略,拥有一个特定的远程方法可能比这个技巧更方便。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.