我正在尝试生成令牌以重置密码,并使用ASP .NET将其发送到用户电子邮件。 但是,在验证之后,用户可以再次单击相同的链接,但仍返回true。我只想配置为一次性使用。 这是代码生成的地方
var code = await identityUserManager.GeneratePasswordResetTokenAsync(user.Id); //the code is generated here
这是验证代码的地方
UserManager.VerifyUserToken(userId, "ResetPassword", code) //still return true after second click in Email
请帮助我!非常感谢!
答案 0 :(得分:0)
有两种方法可以解决此问题:-
通过以下方法1,我们使用令牌实现了到期时间。在这里,如果 到期时间比要求的时间长,用户仍然可以重复使用该代码。更好的解决方案是放置一些RouteGuards
,如方法2所示。这样做将不允许,不允许用户第二次访问重置密码页面,不用强大>生成新代码。因此,此处用户将只能使用一次代码。但是,这种使用不会过期
因此,为了同时拥有这两种好处,我建议同时实现。这样一来,用户将只能使用一次代码,并且在到期之前也只能使用代码。
方法1-(令牌的有效过期时间)
创建一个数据库,该数据库具有3列(TokenCode,IssendToEmailId,ExpireTime)来存储该列,并以EmaildId作为主键,这样就不会在生成令牌后一次向用户颁发一个令牌。在下面提供的ForgetPassword()
中,删除该用户表中的所有前一行,然后插入新数据->令牌代码,用户的电子邮件ID和有效时间,即Datetime.Now.AddMinutes(10);
< / p>
然后在下面提供的ResetPassword()
中,使用电子邮件ID从表中检索数据,并比较Datetime.Now < ExpireTime
(如果为true),继续操作,否则显示过期的代码错误。
方法2-(实施路由防护)
我用于密码重置的代码流程是,在“忘记密码”页面上,我仅要求提供电子邮件地址,然后,让我们单击按钮以启动令牌生成,电子邮件发送等过程。因此,在成功发送电子邮件之后, return Ok()
,然后在sessionStorage
中开始会话并导航到“重置密码”页面。现在,一旦到达这里,我将检查同一会话的可用性,如果未找到,则表明它已被删除,并且将用户导航到我想要的任何位置,但是,如果该会话存在,则我要求输入新密码,并确认新密码,然后说一次按钮单击开始密码重置过程,并在其return Ok()
上删除该会话。
因此,如果用户尝试通过访问重置密码URL尝试再次使用相同的令牌,则他没有该会话,因此可以导航到我想要的任何位置。 这样,我不需要验证用户令牌。
代码=>
忘记密码:-
public async Task<IHttpActionResult> ForgotPassword(ForgotPasswordViewModel model)
{
if (ModelState.IsValid)
{
var user = await UserManager.FindByNameAsync(model.Email);
// If user has to activate his email to confirm his account, the use code listing below
//if (user == null || !(await UserManager.IsEmailConfirmedAsync(user.Id)))
//{
// return Ok();
//}
if (user == null)
{
return NotFound();
}
// For more information on how to enable account confirmation and password reset please visit http://go.microsoft.com/fwlink/?LinkID=320771
// Send an email with this link
string code = await UserManager.GeneratePasswordResetTokenAsync(user.Id);
await UserManager.SendEmailAsync(user.Id, "Reset Password for AJWebApp", $"Please reset your password by using this => {code}");
return Ok();
}
// If we got this far, something failed, redisplay form
return BadRequest(ModelState);
}
重置密码代码:-
public async Task<IHttpActionResult> ResetPassword(ResetPasswordViewModel model)
{
if (!ModelState.IsValid)
{
return BadRequest(ModelState);
}
var user = await UserManager.FindByNameAsync(model.Email);
if (user == null)
{
// Don't reveal that the user does not exist
return Ok();
}
var result = await UserManager.ResetPasswordAsync(user.Id, model.Code, model.Password);
if (result.Succeeded)
{
return Ok();
}
return Ok();
}