核心代码:

    1. // 生成重置密码令牌
    2. var token = await _userManager.GeneratePasswordResetTokenAsync(user);
    3. // 重置用户密码
    4. var result = await _userManager.ResetPasswordAsync(user, model.Token, model.Password);

    找回密码 & 重置密码 完整代码:

    1. #region 找回密码 & 重置密码
    2. [HttpGet]
    3. public IActionResult ForgotPassword()
    4. {
    5. return View();
    6. }
    7. [HttpPost]
    8. public async Task<IActionResult> ForgotPassword(EmailAddressViewModel model)
    9. {
    10. if (ModelState.IsValid)
    11. {
    12. // 通过邮件地址查询用户地址
    13. var user = await _userManager.FindByEmailAsync(model.Email);
    14. // 如果找到了用户并且确认了电子邮件
    15. if (user != null && await _userManager.IsEmailConfirmedAsync(user))
    16. {
    17. // 生成重置密码令牌
    18. var token = await _userManager.GeneratePasswordResetTokenAsync(user);
    19. // 生成密码重置链接
    20. var passwordResetLink = Url.Action("ResetPassword", "Account",
    21. new { email = model.Email, token = token }, Request.Scheme);
    22. // 将密码重置链接记录到文件中
    23. _logger.Log(LogLevel.Warning, passwordResetLink);
    24. // 重定向用户到忘记密码确认视图
    25. return View("ForgotPasswordConfirmation");
    26. }
    27. // 为了避免帐户穷举和暴力攻击,所以不进行用户不存在或邮箱未验证的提示
    28. return View("ForgotPasswordConfirmation");
    29. }
    30. return View(model);
    31. }
    32. // 电子邮箱,重置密码的 token,新密码,确认密码
    33. [HttpGet]
    34. public IActionResult ResetPassword(string token, string email)
    35. {
    36. // 如果密码的 token 或者邮箱地址为空,用户有可能在试图篡改密码重置的 URL
    37. if (token == null || email == null)
    38. {
    39. ModelState.AddModelError("", "当前的密码重置令牌无效");
    40. }
    41. return View();
    42. }
    43. [HttpPost]
    44. public async Task<IActionResult> ResetPassword(ResetPasswordViewModel model)
    45. {
    46. if (ModelState.IsValid)
    47. {
    48. // 通过电子邮件查找用户
    49. var user = await _userManager.FindByEmailAsync(model.Email);
    50. if (user != null)
    51. {
    52. // 重置用户密码
    53. var result = await _userManager.ResetPasswordAsync(user, model.Token, model.Password);
    54. if (result.Succeeded)
    55. {
    56. // 密码成功重置后,如果当前账户被锁定,则设置该账户锁定结束日期为当前 UTC 日期时间。
    57. // 这样用户就可以用新密码登录系统。
    58. if (await _userManager.IsLockedOutAsync(user))
    59. {
    60. // DateTimeOffset 指 UTC 时间即格林威治时间
    61. await _userManager.SetLockoutEndDateAsync(user, DateTimeOffset.UtcNow);
    62. }
    63. return View("ResetPasswordConfirmation");
    64. }
    65. // 告诉它验证不通过的错误信息
    66. foreach (var error in result.Errors)
    67. {
    68. ModelState.AddModelError("", error.Description);
    69. }
    70. return View(model);
    71. }
    72. // 为了避免帐户穷举和暴力攻击,不要提示用户不存在
    73. return View("ResetPasswordConfirmation");
    74. }
    75. // 如果模型验证未通过,则显示验证错误
    76. return View(model);
    77. }
    78. #endregion 找回密码 & 重置密码

    其他代码请参考 StudentManagement

    效果:
    image.png
    image.png