这节我们主要介绍重置密码功能,当一个用户忘记自己密码时需要选择重置密码,使用ASP.NET Core Identity进行重置密码是非常方便的
1、ASP.NET Core Identity 重置密码
接下来我们看一下Identity中是如何重置密码,当一个用户忘记密码时,我们将他带入进入忘记密码页面,如下图所示:
这个页面会向用户指定的邮箱发送一个重置密码的URL,当用户点击这个URL时,会携带上相应的token和Email链接到重置密码页面,下图为重置密码页面:
在应用程序中添加AddDefaultTokenProviders扩展方法启用token生成功能。下面代码:
builder.Services.AddIdentity<AppUser,IdentityRole>().
AddEntityFrameworkStores<AppIdentityDbContext>().
AddDefaultTokenProviders();
//dot net 6
builder.Services.Configure<DataProtectionTokenProviderOptions>(opts => opts.TokenLifespan = TimeSpan.FromHours(10));
3、创建一个忘记密码功能
[ ]
public IActionResult ForgotPassword()
{
return View();
}
[ ]
[ ]
public async Task<IActionResult> ForgotPassword([Required] string email)
{
if (!ModelState.IsValid)
{
return View(email);
}
var appUser = await _userManager.FindByEmailAsync(email);
if (appUser == )
{
return RedirectToAction(nameof(ForgotPasswordConfirmation));
}
var token = await _userManager.GeneratePasswordResetTokenAsync(appUser);
var url = Url.Action("ResetPassword", "Account", new { Email = email, Token = token }, Request.Scheme);
_emailService.Send(appUser!.Email ?? "450190369@qq.com", "重置密码", $"{url}");
return RedirectToAction("ForgotPasswordConfirmation");
}
[ ]
public IActionResult ForgotPasswordConfirmation()
{
return View();
}
var appUser = await _userManager.FindByEmailAsync(email);
if (appUser == )
{
return RedirectToAction(nameof(ForgotPasswordConfirmation));
}
var token = await _userManager.GeneratePasswordResetTokenAsync(appUser);
var url = Url.Action("ResetPassword", "Account", new { Email = email, Token = token }, Request.Scheme);
_emailService.Send(appUser!.Email ?? "450190369@qq.com", "重置密码", $"{url}");
enAsync 方法创建了一个重置密码的token,我们将这个token添加到链接地址中并且将这个链接地址发送给用户,用户使用这个链接来重置密码
在Views->Account中添加如下2个View文件,ForgotPassword.cshtml&ForgotPasswordConfirmation.cshtml , 代码如下:
@{
ViewData["Title"] = "忘记密码";
}
<div class="container">
<form asp-action="ForgotPassword" method="post">
<div class="mb-3 row align-items-center">
<div class="col-sm-1">
<label class="control-label">电子邮箱</label>
</div>
<div class="col-sm-11">
<input name="email" class="form-control" />
</div>
</div>
<div class="mb-3 row align-items-center">
<div class="col-sm-11 offset-sm-1">
<button class="btn btn-primary" type="submit">发送邮件</button>
</div>
</div>
</form>
</div>
@{
ViewData["Title"] = "忘记密码确认";
}
<h1>忘记密码确认</h1>
<p>
邮件已经发送,请检查邮件并重置密码
</p>
运行应用程序进入忘记密码URL并且输入邮件地址,点击发送邮件。下图:
发送完邮件之后会跳转到如下页面:
下面我们打开邮箱查看一下刚才发的邮件:
[ ]
public IActionResult ResetPassword(string token, string email)
{
var resetPassword = new ResetPassword() { Token = token, Email = email };
return View(resetPassword);
}
[ ]
[ ]
public async Task<IActionResult> ResetPassword(ResetPassword resetPassword)
{
if (!ModelState.IsValid)
return View(resetPassword);
var appUser = await _userManager.FindByEmailAsync(resetPassword.Email);
if (appUser == )
RedirectToAction("ResetPasswordConfirmation");
var resetPassResult = await _userManager.ResetPasswordAsync(appUser, resetPassword.Token, resetPassword.Password);
if (!resetPassResult.Succeeded)
{
foreach (var error in resetPassResult.Errors)
ModelState.AddModelError(error.Code, error.Description);
return View();
}
return RedirectToAction("ResetPasswordConfirmation");
}
public class ResetPassword
{
[ ]
[ ]
public string Password { get; set; } = !;
[ ]
[ ]
public string ConfirmPassword { get; set; } = !;
public string Email { get; set; } = !;
public string Token { get; set; } = !;
}
ResetPassword.cshtml
@model ResetPassword
@{
ViewData["Title"] = "重置密码";
}
<div class="text-danger" asp-validation-summary="All"></div>
<form asp-action="ResetPassword" method="post">
<div class="mb-3 row align-items-center">
<div class="col-sm-1">
<label asp-for="Password"></label>
</div>
<div class="col-sm-11">
<input asp-for="Password" class="form-control" />
</div>
</div>
<div class="mb-3 row align-items-center">
<div class="col-sm-1">
<label asp-for="ConfirmPassword"></label>
</div>
<div class="col-sm-11">
<input asp-for="ConfirmPassword" class="form-control" />
</div>
</div>
<input type="hidden" asp-for="Email" class="form-control" />
<input type="hidden" asp-for="Token" class="form-control" />
<div class="mb-3 row align-items-center">
<div class="col-sm-11 offset-sm-1">
<button class="btn btn-primary" type="submit">提交</button>
</div>
</div>
</form>
ResetPasswordConfirmation.cshtml
@{
ViewData["Title"] = "重置密码确认";
}
<h1>重置密码确认</h1>
<p>
密码已经被重置. 请 <a asp-action="Login">登录</a>
</p>
ResetPassword视图是用户修改密码
ResetPasswordConfirmation 视图提示用户密码已经修改成功
6、测试修改密码特性
首先我们进入忘记密码页面,(url –https://localhost:7296/Ac
count/ForgotPassword) 输入邮件。点击发送邮件,会向我们指定的邮箱发送电子邮件,将邮箱中收到的url输入到浏览器中。如下图所示:
注意Token和Email添加到了url查询字符串中,这两个值通过ResetPassword Get 版本的方法传递到了View,现在可以修改我们的密码了,修改完之后会跳转到如下页面:
这节我们主要实现了实现忘记密码功能,注册token并且设置token的声明周期,实现重置密码功能
源代码地址:
https://github.com/bingbing-gui/Asp.Net-Core-Skill/tree/master/AspNetCore.Identity/Identity