Javascript 使用访问令牌重置环回密码
我正在做一个使用环回作为框架的项目,包括用户和身份验证。我添加了一个在电子邮件中生成并发送的密码重置路由,一切似乎都正常工作。最近,我发现密码重置似乎不起作用。此处重置密码的过程如下:Javascript 使用访问令牌重置环回密码,javascript,angularjs,node.js,loopbackjs,strongloop,Javascript,Angularjs,Node.js,Loopbackjs,Strongloop,我正在做一个使用环回作为框架的项目,包括用户和身份验证。我添加了一个在电子邮件中生成并发送的密码重置路由,一切似乎都正常工作。最近,我发现密码重置似乎不起作用。此处重置密码的过程如下: 用户的呼叫密码重置方法 从重置事件发送电子邮件,包括用户ID和访问令牌 从重置链接,将$http.defaults.headers.common.authorization设置为传递的令牌 调用user.prototype$updateAttributes(由lb ng生成)以基于表单更新密码属性 预期的行为
- 用户的呼叫密码重置方法
- 从重置事件发送电子邮件,包括用户ID和访问令牌
- 从重置链接,将$http.defaults.headers.common.authorization设置为传递的令牌
- 调用user.prototype$updateAttributes(由lb ng生成)以基于表单更新密码属性
...
{
"accessType": "*",
"principalType": "ROLE",
"principalId": "$owner",
"permission": "ALLOW"
},
{
"accessType": "EXECUTE",
"principalType": "ROLE",
"principalId": "$owner",
"permission": "ALLOW",
"property": "updateAttributes"
}
...
auth.js
...
resetPassword: function(user) {
return MyUser.prototype$updateAttributes(user, user).$promise;
}
...
找出问题所在。在我们的应用程序服务器中,我们没有使用环回的令牌中间件。添加
app.use(loopback.token())代码>在启动服务器之前,会导致重置链接中提供的访问令牌按预期工作 @Elvis让我走上了正确的道路。这里有一个更完整的答案供其他遇到这个问题的人参考。环回文档在这方面非常有限
确保您在电子邮件中同时获得用户id和令牌,并在表单中填充它们
从表单中,以下代码执行此任务:
function resetPassword(id, token, password) {
$http.defaults.headers.common.authorization = token;
return User
.prototype$updateAttributes({id:id}, {
password: password
})
.$promise;
}
虽然上述所有答案都将被证明是有帮助的,但请注意,在验证过程中,当它被证明无效时,会出现回送。代币将不见了。因此,当您正在努力解决401的问题时,请确保每次尝试新的代码迭代时都创建了一个新的密码重置令牌
否则,您可能会发现自己正在使用完全健康的代码来更改密码,但使用的令牌在代码的上一次迭代中已被删除,从而导致错误的结论,即当您看到另一个401时,您需要处理代码
在我的特殊情况下,访问令牌存储在SQL Server数据库中,由于引入了时区问题,该令牌总是会立即过期,因为我已将其设置为false。这会导致所有新令牌在过去为7200秒,这比密码重置令牌有效的900秒还要多。我没有注意到这些代币立即被销毁,并得出结论,当我看到401的回报时,我的代码仍然存在问题。事实上,401是由使用服务器上已经存在的令牌引起的 这比应该的要复杂得多。以下是我的完整解决方案:
1) 我在服务器端公开了一个新方法,该方法从令牌更新密码
Member.updatePasswordFromToken = (accessToken, __, newPassword, cb) => {
const buildError = (code, error) => {
const err = new Error(error);
err.statusCode = 400;
err.code = code;
return err;
};
if (!accessToken) {
cb(buildError('INVALID_TOKEN', 'token is null'));
return;
}
Member.findById(accessToken.userId, function (err, user) {
if (err) {
cb(buildError('INVALID_USER', err));
return;
};
user.updateAttribute('password', newPassword, function (err, user) {
if (err) {
cb(buildError('INVALID_OPERATION', err));
return;
}
// successful,
// notify that everything is OK!
cb(null, null);
});
});
}
我还定义了可访问性:
Member.remoteMethod('updatePasswordFromToken', {
isStatic: true,
accepts: [
{
arg: 'accessToken',
type: 'object',
http: function(ctx) {
return ctx.req.accessToken;
}
},
{arg: 'access_token', type: 'string', required: true, 'http': { source: 'query' }},
{arg: 'newPassword', type: 'string', required: true},
],
http: {path: '/update-password-from-token', verb: 'post'},
returns: {type: 'boolean', arg: 'passwordChanged'}
});
在客户端,我只是这样称呼它:
this.memberApi.updatePasswordFromToken(token, newPassword);
我完全被这件事弄糊涂了。为什么我不能更新我自己的任何属性?你能附加一些代码吗?401似乎表明你没有被授权在这里做一些事情,包括相关的,微小的部分。你能更具体地说,我需要在哪里改变什么?我也有同样的问题,但仍然不知道你做了什么,使这个work@EdmundoDelGusto将其添加到boot/server.js
文件中,在app.start
函数示例之前,用于环回中的示例用户管理,您需要在电子邮件连接器中设置电子邮件和密码。整洁地给出每一件事,你在哪里添加这个函数?在模型定义中,我对远程方法声明做了一个小的更改,但总体上是相同的代码。我没有使用{arg:'accessToken',type:'object'…},而是将整个请求发送到我的方法,并从那里获取令牌ID