方法名称 |
描述 |
FindByIdAsync(id) |
根据指定的ID查询用户对象 |
CreateAsync(user,password) |
注册一个新的用户 |
UpdateAsync(user) |
修改一个已经存在的用户 |
DeleteAsync(user) |
移除一个指定的用户 |
AddToRoleAsync(user, name) |
给用户添加角色 |
RemoveFromRoleAsync(user, name) |
从角色中移除用户 |
GetRolesAsync(user) |
获取角色名字列表 |
IsInRoleAsync(user, name) |
返回一个标志,表示是否是给与角色名字的成员 |
名称 |
描述 |
Id |
包含用户唯一ID |
UserName |
包含用户名称 |
|
包含用户Email |
// 堆代码 duidaima.com public class User { [Required] [DisplayName("用户名")] public string Name { get; set; } = null!; [Required] [DisplayName("邮箱")] [RegularExpression("^[a-zA-Z0-9_\\.-]+@([a-zA-Z0-9-]+\\.)+[a-zA-Z]{2,6}$", ErrorMessage = "电子邮件格式不正确")] public string Email { get; set; } = null!; [Required] [DataType(DataType.Password)] [DisplayName("密码")] public string Password { get; set; } = null!; }在Controllers文件夹下新增一个新的AdminController类,在该控制器中创建CURD方法,AdminController如下:
public class AdminController : Controller { private UserManager<AppUser> _userManager; public AdminController(UserManager<AppUser> userManager) { _userManager = userManager; } public IActionResult Index() { return View(); } }在AdminController的构造函数中引用UserManager类,接下来我们添加Create方法来创建新用户,如下代码:
public ViewResult Create()=>View(); [HttpPost] public async Task<IActionResult> Create(User user) { if (ModelState.IsValid) { AppUser appUser = new AppUser { UserName = user.Name, Email = user.Email, }; var identityResult = await _userManager.CreateAsync(appUser, user.Password); if (identityResult.Succeeded) return RedirectToAction("Index", "Admin"); else foreach (IdentityError error in identityResult.Errors) ModelState.AddModelError("", error.Description); } return View(user); }Post版本的Create方法创建一个新的Identity用户,该方法的参数获取一个User类并检查模型绑定是否成功。如果模型绑定成功创建一个AppUser类的实例并且将UserName和Email赋值给该对象。
AppUser appUser = new AppUser { UserName = user.UserName, Email = user.Email, };在这个之后,我们通过调用UserManager类的CreateAsync创建一个用户,CreateAsync方法有两个参数,一个是AppUser对象类,第二个是Password。该方法返回IdentityResult类型
var identityResult = await _userManager.CreateAsync(appUser, user.Password);IdentityResult 类包含下面属性:
if (identityResult.Succeeded) { return RedirectToAction("Index", "Admin"); } else { foreach (IdentityError error in identityResult.Errors) { ModelState.AddModelError("", error.Description); } }最后一行我们将user返回到Create视图-return View(user),将错误信息显示在浏览器提示用户改正
@model User @{ ViewData["Title"] = "新增用户"; } <div asp-validation-summary="All" class="text-danger"></div> <form class="form-horizontal" role="form" method="post"> <div class="mb-3 row"> <label asp-for="Name" class="col-sm-1 control-label"></label> <div class="col-sm-11"> <input asp-for="Name" class="form-control" /> </div> </div> <div class="mb-3 row"> <label asp-for="Email" class="col-sm-1 control-label"></label> <div class="col-sm-11"> <input asp-for="Email" class="form-control" /> </div> </div> <div class="mb-3 row"> <label asp-for="Password" class="col-sm-1 control-label"></label> <div class="col-sm-11"> <input asp-for="Password" class="form-control" /> </div> </div> <div class="mb-3 row"> <div class="col-sm-11 offset-sm-1"> <button type="submit" class="btn btn-primary">保存</button> <button asp-action="Index" class="btn btn-secondary"> 返回 </button> </div> </div> </form>用户可以通过该表单将用户名&邮件&密码提交AdminControlle的Create方法,从而保存到数据库中。接下来我们创建一个新的用户,运行应用程序在浏览器中输入下面地址:https://localhost:7296/Admin/Create
public class AdminController : Controller { private UserManager<AppUser> _userManager; public AdminController(UserManager<AppUser> userManager) { _userManager = userManager; } public IActionResult Index() { return View(_userManager.Users); } }我们将所有的用户以IEnumerable形式返回到View。现在我们在Views->Admin目录下创建Index.cshtml视图,显示用户的详细信息。
@model IEnumerable<AppUser> @{ ViewData["Title"] = "用户列表"; } <div class="container"> <div class="row mb-3"> <div class="col-sm-3"> <a asp-action="Create" class="btn btn-primary">新增</a> </div> <div class="col-sm-3"></div> <div class="col-sm-3"></div> <div class="col-sm-3"></div> </div> <div class="row mb-3"> <div class="col-sm"> <table class="table table-bordered align-middle"> <thead> <tr> <th>编号</th> <th>名称</th> <th>邮件</th> </tr> </thead> <tbody> @foreach (AppUser user in Model) { <tr> <td>@user.Id</td> <td>@user.UserName</td> <td>@user.Email</td> </tr> } </tbody> </table> </div> </div> </div>在这个View中接受一个IEnumerable<AppUser>的模型类,使用foreach循环该类将所有用户的信息显示在表格内,我们测试一下该功能,在浏览其中输入https://localhost:7296/
@model IEnumerable<AppUser> @{ ViewData["Title"] = "用户列表"; } <div class="container"> <div class="row mb-3"> <div class="col-sm-3"> <a asp-action="Create" class="btn btn-primary">新增</a> </div> <div class="col-sm-3"></div> <div class="col-sm-3"></div> <div class="col-sm-3"></div> </div> <div class="row mb-3"> <div class="col-sm"> <table class="table table-bordered align-middle"> <thead> <tr> <th>编号</th> <th>名称</th> <th>邮件</th> <th>编辑</th> </tr> </thead> <tbody> @foreach (AppUser user in Model) { <tr> <td>@user.Id</td> <td>@user.UserName</td> <td>@user.Email</td> <td> <a class="btn btn-primary btn-sm" asp-action="Update" asp-route-id="@user.Id">编辑</a> </td> </tr> } </tbody> </table> </div> </div> </div>我们需要在AdminController的构造函数添加IPasswordHasher依赖。使用它来获取用户密码的哈希值。出于安全目ASP.NET Core Identity存储用户密码使用的是用户密码的哈希值,而不是平面文本。因此黑客获取到用户信息,是无法登录
public class AdminController : Controller { // 堆代码 duidaima.com private UserManager<AppUser> _userManager; private IPasswordHasher<AppUser> _passwordHasher; public AdminController(UserManager<AppUser> userManager, IPasswordHasher<AppUser> passwordHash) { _userManager = userManager; _passwordHasher = passwordHash; } }我们在AdminController中添加Update 方法,代码如下:
public async Task<IActionResult> Update(string Id) { var appUser = await _userManager.FindByIdAsync(Id); if (appUser != null) { var updateUserDTO = new UpdateUserDTO(); updateUserDTO.Id = appUser.Id; updateUserDTO.Name = appUser.UserName ?? ""; updateUserDTO.Email = appUser.Email == null ? "" : appUser.Email; return View(updateUserDTO); } else { return RedirectToAction("Index"); } } [HttpPost] public async Task<IActionResult> Update(UpdateUserDTO updateUserDTO) { var appUser = await _userManager.FindByIdAsync(updateUserDTO.Id); if (appUser != null) { if (updateUserDTO.Email != null) appUser.Email = updateUserDTO.Email; else ModelState.AddModelError("", "邮箱不能为空"); if (updateUserDTO.Name != null) appUser.UserName = updateUserDTO.Name; else ModelState.AddModelError("", "用户名不能为空"); if (updateUserDTO.Password != null) appUser.PasswordHash = _passwordHasher.HashPassword(appUser, updateUserDTO.Password); else ModelState.AddModelError("", "密码不能为空"); if (!string.IsNullOrEmpty(updateUserDTO.Email) && !string.IsNullOrEmpty(updateUserDTO.Password)) { var result = await _userManager.UpdateAsync(appUser); if (result.Succeeded) return RedirectToAction("Index"); else { foreach (IdentityError error in result.Errors) { ModelState.AddModelError("", error.Description); } } } } else ModelState.AddModelError("", "没有发现该用户"); return View(updateUserDTO); }HTTP GET版本的Update方法参数接受一个字符串类型的Id。这个Id表示用户注册时生成的Id,用UserManager类FindByIdAsync()方法从Identity数据库中查找该用户记录,该方法提供了通过用户Id查找用户信息
var appUser = await _userManager.FindByIdAsync(Id);每次查找完用户信息后会将用户信息作为实体发送到Update.cshtml 视图。当用户点击提交按钮时会将表单的数据提交到HTTP POST 版本的Update方法,该方法会更新用户数据。首先使用FindByIdAsync()方法获取用户信息:
var appUser = await _userManager.FindByIdAsync(Id);如果AppUser对象不是null,我们检查email和password是否为null,如果不为null我们更新AppUser类Email和PasswordHash属性值,我们将修改后的AppUser作为参数传递给UserManager类的UpdateAsync方法
if (updateUserDTO.Email != null) appUser.Email = updateUserDTO.Email; else ModelState.AddModelError("", "邮箱不能为空"); if (updateUserDTO.Password != null) appUser.PasswordHash = _passwordHasher.HashPassword(appUser, updateUserDTO.Password); else ModelState.AddModelError("", "密码不能为空");注意我们使用HashPassword()方法生成用户密码的哈希值
appUser.PasswordHash = _passwordHasher.HashPassword(appUser, updateUserDTO.Password);使用UpdateAsync方法更新,这个方法参数是一个AppUser的对象。代码如下:
var result = await _userManager.UpdateAsync(appUser); if (result.Succeeded) return RedirectToAction("Index"); else foreach (IdentityError error in result.Errors) Errors(error);如果更新方法没有执行成功,我们需要调用Errors将对应的错误信息添加到ModelState中,并将这些错误信息显示在浏览器上。代码如需:
void Errors(IdentityResult result) { foreach (IdentityError error in result.Errors) ModelState.AddModelError("", error.Description); }在Views->Admin文件夹下创建Update.cshtml 文件:
@model UpdateUserDTO @{ ViewData["Title"] = "修改用户"; } <div asp-validation-summary="All" class="text-danger"></div> <form class="form" method="post" role="form"> <div class="row mb-3"> <label asp-for="Id" class="col-sm-1 control-label"></label> <div class="col-sm-11"> <input asp-for="Id" class="form-control" disabled /> </div> </div> <div class="mb-3 row"> <label asp-for="Name" class="col-sm-1 control-label"></label> <div class="col-sm-11"> <input asp-for="Name" class="form-control" /> </div> </div> <div class="row mb-3"> <label asp-for="Email" class="col-sm-1 form-label"></label> <div class="col-sm-11"> <input asp-for="Email" class="form-control" /> </div> </div> <div class="row mb-3"> <label asp-for="Password" class="col-sm-1 form-label"></label> <div class="col-sm-11"> <input asp-for="Password" class="form-control" /> </div> </div> <div class="row mb-3"> <div class="col-sm-11 offset-sm-1"> <button class="btn btn-primary">保存</button> <button asp-action="index" class="btn btn-secondary">返回</button> </div> </div> </form> public class UpdateUserDTO { [Required] [DisplayName("编号")] public string Id { get; set; } = null!; [Required] [DisplayName("用户名")] public string Name { get; set; }=null!; [Required] [DisplayName("邮箱")] [RegularExpression("^[a-zA-Z0-9_\\.-]+@([a-zA-Z0-9-]+\\.)+[a-zA-Z]{2,6}$", ErrorMessage = "E-mail is not valid")] public string Email { get; set; } = null!; [Required] [DataType(DataType.Password)] [DisplayName("密码")] public string Password { get; set; } = null!; }我们测试一下更新功能,启动应用程序在浏览器中输入如下地址:https://localhost:7296/Admin,点击更新按钮会跳转到对应的更新页面,输入邮箱和密码并且点击保存按钮将会更新数据库中的用户记录。
[HttpPost] public async Task<IActionResult> Delete(string Id) { var appUser = await _userManager.FindByIdAsync(Id); if (appUser != null) { var result = await _userManager.DeleteAsync(appUser); if (result.Succeeded) return RedirectToAction("Index"); else Errors(result); } else ModelState.AddModelError("", "没有发现该用户"); return View("Index", _userManager.Users); }删除方法接受一个用户Id并且调用FindByIdAsync()方法查询对应用户记录,获取到相匹配的用户之后使用DeleteAsync方法删除。代码如下:
var result = await _userManager.DeleteAsync(appUser);如果删除成功,用户会跳转到Index方法,否则会将相应的错误显示到浏览器,我们在Index.cshtml页面添加删除按钮。代码如下:
@model IEnumerable<AppUser> @{ ViewData["Title"] = "用户列表"; } <div class="container"> <div class="row mb-3"> <div class="col-sm-3"> <a asp-action="Create" class="btn btn-primary">新增</a> </div> <div class="col-sm-3"></div> <div class="col-sm-3"></div> <div class="col-sm-3"></div> </div> <div class="row mb-3"> <div class="col-sm"> <table class="table table-bordered align-middle"> <thead> <tr> <th>编号</th> <th>名称</th> <th>邮件</th> <th>编辑</th> <th>删除</th> </tr> </thead> <tbody> @foreach (AppUser user in Model) { <tr> <td>@user.Id</td> <td>@user.UserName</td> <td>@user.Email</td> <td> <a class="btn btn-primary btn-sm" asp-action="Update" asp-route-id="@user.Id">编辑</a> </td> <td> <form method="post" asp-action="Delete" asp-route-id="@user.Id" role="form"> <button type="submit" class="btn btn-danger btn-sm">删除</button> </form> </td> </tr> } </tbody> </table> </div> </div> </div>运行应用程序,在浏览器中输入https://localhost:7296/admin地址,我们看到所有的Identity User记录旁边有都一个删除按钮,当我们点击删除按钮时,会将用户从数据库中删除。