如何检查密码重置令牌是否已过期?

Ste*_*ven 5 c# asp.net-identity asp.net-core

我正在使用ASP.NET Identity,并且已经具备基本的“忘记密码/重置密码”功能。

当您填写忘记密码的表格时,它将使用创建一个重置令牌 _userManager.GeneratePasswordResetTokenAsync(user)

[HttpPost]
[AllowAnonymous]
[ValidateAntiForgeryToken]
public async Task<IActionResult> ForgotPassword(ForgotPasswordViewModel model)
{
    if (ModelState.IsValid)
    {
        var user = await _userManager.FindByNameAsync(model.Email);
        if (user == null || !(await _userManager.IsEmailConfirmedAsync(user)))
        {
            return View("ForgotPasswordConfirmation");
        }

        var code = await _userManager.GeneratePasswordResetTokenAsync(user);
        var callbackUrl = Url.Action("ResetPassword", "Account", new { userId = user.Id, code = code }, protocol: HttpContext.Request.Scheme);
        await _emailSender.SendEmailAsync(model.Email, "Reset Password",
               $"Please reset your password by clicking here: <a href='{callbackUrl}'>link</a>");
        return View("ForgotPasswordConfirmation");
    }

    // If we got this far, something failed, redisplay form
    return View(model);
}
Run Code Online (Sandbox Code Playgroud)

我注意到,“重置密码”页面的唯一验证是检查代码是否为null,而不是检查其是否仍然有效。

[HttpGet]
[AllowAnonymous]
public IActionResult ResetPassword(string code = null)
{
    if (code == null)
    {
        throw new Exception("A code must be supplied for password reset.");
    }
    var model = new ResetPasswordViewModel { Code = code };
    return View(model);
}
Run Code Online (Sandbox Code Playgroud)

在您尝试重设密码并调用之前,它实际上不会检查令牌是否有效。 _userManager.ResetPasswordAsync(user, model.Code, model.Password)

我希望能够验证代码在他们单击“重置密码”页面以向用户显示消息时(而不是在他们尝试重置密码之后)仍然有效。

有没有办法检查它是否有效?

Wou*_*ter 8

以下代码用于验证重置令牌是否有效:

1.创建代码并将其发送给用户

var code = await this._userManager.GeneratePasswordResetTokenAsync(user);
Run Code Online (Sandbox Code Playgroud)

2.验证令牌

[HttpGet]
public async Task<IActionResult> ResetPassword(string UserId, string token)
{
    ...

    ApplicationUser user = //get user;


    if(!await this._userManager.VerifyUserTokenAsync(user,this._userManager.Options.Tokens.PasswordResetTokenProvider, "ResetPassword", token)){
        ViewBag.Message = this._localizer["tokenNotValid"].Value;
    }

    ...
}
Run Code Online (Sandbox Code Playgroud)

请参阅UserManager代码:https : //github.com/aspnet/Identity/blob/rel/2.0.0/src/Microsoft.Extensions.Identity.Core/UserManager.cs#L29


Jer*_*oen 5

如果您检查该UserManager.ResetPasswordAsync(...)方法,则通过该VerifyUserTokenAsync方法进行跟踪,只需执行以下操作:

// Make sure the token is valid
var result = await _tokenProviders[tokenProvider].ValidateAsync(purpose, token, this, user);
Run Code Online (Sandbox Code Playgroud)

您也可以自己做,知道:

  • 您可以向DI框架(例如,通过控制器构造函数)询问令牌提供商,以了解您的情况;
  • purpose仅仅是硬编码的"ResetPassword"字符串 ;
  • token是用户使用的代码;
  • user你应该能够取决于如何你的看法,电子邮件,网址搞定,无论是设置(默认的例子并不包括这个我想,但你可以很容易地把user.Id之前的“忘记密码的URL”令牌本身,并在需要时将其提取)。

然后,您可以自称ValidateAsync并相应调整视图。