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

Posted

技术标签:

【中文标题】如何检查密码重置令牌是不是已过期?【英文标题】:How can I check if a password reset token is expired?如何检查密码重置令牌是否已过期? 【发布时间】:2018-03-12 09:30:12 【问题描述】:

我正在使用 ASP.NET 身份,并且我有基本的忘记密码/重置密码功能。

当您填写忘记密码的表单时,它会使用_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);

我注意到重置密码页面的唯一验证是检查代码是否为空,而不是检查它是否仍然有效或未过期。

[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);

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

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

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

【问题讨论】:

UserTokenProvider.ValidateAsync("ResetPassword", token, this, user)) ??? 谢谢,我以为有可用的方法,只是找不到 什么是 UserTokenProvider 类? @steven:如果你能发布你的问题的解决方案,那就太好了? 【参考方案1】:

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

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

var code = await this._userManager.GeneratePasswordResetTokenAsync(user);

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;
    

    ...

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

【讨论】:

【参考方案2】:

如果您检查UserManager.ResetPasswordAsync(...) 方法,跟踪到VerifyUserTokenAsync 方法,它只是这样做:

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

你也可以自己做,知道:

您可以根据您的情况向 DI 框架(例如通过您的控制器构造函数)询问令牌提供程序; purpose 就是the hardcoded "ResetPassword" string; token 是用户正在使用的代码; user 你应该能够获得取决于你的视图、电子邮件、url 和任何设置的方式(我认为默认示例不包括这个,但你可以轻松地将@987654331 @在令牌本身之前的“忘记密码url”中,并在需要时将其提取)。

然后您可以自己拨打ValidateAsync 并相应地调整视图。

【讨论】:

以上是关于如何检查密码重置令牌是不是已过期?的主要内容,如果未能解决你的问题,请参考以下文章

在Linux中,MySQL密码没过期,刚重置完,提示已过期

以 html 帖子形式存储重置密码令牌是不是安全?

设计:如何自定义重置密码令牌?

如何从 ASP.NET Core 中的密码重置令牌中检索用户?

生成重置密码令牌的最佳实践

CloudKit 错误:更改令牌已过期,需要重置