使用Loopback实现更改密码

我试图用Loopback的内置方法实现更改密码function,它工作正常,但它不会更新密码与hash相反,它只是保存在数据库中的纯文本。 我在这个项目中使用loopback-component-passport npm包。 我search了很多网站,但我无法find正确的方法来实现此function。 有没有人有想法如何做到这一点?

 //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'}); }); } }); }); }); 

使用在源代码中看到的内置的User.hashPassword

 //Hash the plain password user.updateAttribute('password', User.hashPassword(req.body.password), function(err, user) { ... }); 

这实际上是一个在loopback-datasource-juggler 2.45.0中引入的bug。 密码应该默认散列。

https://github.com/strongloop/loopback-datasource-juggler/issues/844

https://github.com/strongloop/loopback/issues/2029

所以,要小心,如果你使用user.hashpassword它可能无法在将来的版本,当这是固定的,因为它可能散列一个已经散列的PW如果不正确,但应该已经检查了长度加检查$ 2 $或无论起始位是散列值。

编辑 :安装loopback-datasource-juggler的2.45.1,它应该是固定的。

这是我的“完整”解决scheme,在LoopBack / StrongLoop-IBM项目中实现特定的updatePassword远程方法。 请确认loopback-datasource-juggler包的版本高于或等于2.45.1( npm list loopback-datasource-juggler )。 我的用户模型被称为MyUserModel并从内置模型inheritanceUser

“我的用户,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 (eg 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'} } ); ... }; 

“我的用户,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" } ... ], ... } 

注意:可以使用MyUserModel上的PUT请求执行相同的function,并在主体中指定{“password”:“… newpassword …”}。 但是为了强制执行新密码的安全策略,使用特定的远程方法可能比这个方法更为方便。