15 用户管理.mp4 (117.94MB) 注:

  • 从这一讲开始的源码,视频作者杨旭大神都放在了自己的 GitHub
  • 我也将我学习的代码放到了 GitHub

    准备工作

  1. GitHub 下载源码
  2. 打开 15 start 项目
  3. 打开程序包管理控制台,更新数据库
    1. Update-Database -Context HeavyContext
    2. Update-Database -Context ApplicationDbContext

      使用 Identity

      创建项目

      创建项目使用 ASP.NET Core MVC 模板 + 身份认证选择 个人。

自动生成的 Startup 里面的部分代码就启用了 Identity:

  1. public void ConfigureServices(IServiceCollection services)
  2. {
  3. ...
  4. services.AddDefaultIdentity<IdentityUser>()
  5. .AddDefaultUI(UIFramework.Bootstrap4)
  6. .AddEntityFrameworkStores<ApplicationDbContext>();
  7. ...
  8. }
  9. public void Configure(IApplicationBuilder app, IHostingEnvironment env)
  10. {
  11. ...
  12. app.UseCookiePolicy();
  13. app.UseAuthentication();
  14. ...
  15. }

UserController

通过依赖注入的 UserManager 实现对 User 的操控。

  1. [Authorize]
  2. public class UserController : Controller
  3. {
  4. private readonly UserManager<ApplicationUser> _userManager;
  5. public UserController(UserManager<ApplicationUser> userManager)
  6. {
  7. _userManager = userManager;
  8. }
  9. public async Task<IActionResult> Index()
  10. {
  11. var users = await _userManager.Users.ToListAsync();
  12. return View(users);
  13. }
  14. public IActionResult AddUser()
  15. {
  16. return View();
  17. }
  18. [HttpPost]
  19. public async Task<IActionResult> AddUser(UserCreateViewModel userAddViewModel)
  20. {
  21. if (!ModelState.IsValid)
  22. {
  23. return View(userAddViewModel);
  24. }
  25. var user = new ApplicationUser
  26. {
  27. UserName = userAddViewModel.UserName,
  28. Email = userAddViewModel.Email,
  29. IdCard = userAddViewModel.IdCard,
  30. BirthDate = userAddViewModel.BirthDate
  31. };
  32. var result = await _userManager.CreateAsync(user, userAddViewModel.Password);
  33. if (result.Succeeded)
  34. {
  35. return RedirectToAction("Index");
  36. }
  37. foreach (var error in result.Errors)
  38. {
  39. ModelState.AddModelError(string.Empty, error.Description);
  40. }
  41. return View(userAddViewModel);
  42. }
  43. public async Task<IActionResult> EditUser(string id)
  44. {
  45. var user = await _userManager.FindByIdAsync(id);
  46. if (user == null)
  47. {
  48. return RedirectToAction("Index");
  49. }
  50. var userEditViewModel=new UserEditViewModel
  51. {
  52. UserName = user.UserName,
  53. Email = user.Email
  54. };
  55. return View(userEditViewModel);
  56. }
  57. [HttpPost]
  58. public async Task<IActionResult> EditUser(string id, UserEditViewModel userEditViewModel)
  59. {
  60. var user = await _userManager.FindByIdAsync(id);
  61. if (user == null)
  62. {
  63. return RedirectToAction("Index");
  64. }
  65. user.UserName = userEditViewModel.UserName;
  66. user.Email = userEditViewModel.Email;
  67. user.IdCard = userEditViewModel.IdCard;
  68. user.BirthDate = userEditViewModel.BirthDate;
  69. var result = await _userManager.UpdateAsync(user);
  70. if (result.Succeeded)
  71. {
  72. return RedirectToAction("Index");
  73. }
  74. ModelState.AddModelError(string.Empty, "更新用户信息时发生错误");
  75. return View(userEditViewModel);
  76. }
  77. [HttpPost]
  78. public async Task<IActionResult> DeleteUser(string id)
  79. {
  80. var user = await _userManager.FindByIdAsync(id);
  81. if (user != null)
  82. {
  83. var result = await _userManager.DeleteAsync(user);
  84. if (result.Succeeded)
  85. {
  86. return RedirectToAction("Index");
  87. }
  88. ModelState.AddModelError(string.Empty, "删除用户时发生错误");
  89. }
  90. else
  91. {
  92. ModelState.AddModelError(string.Empty, "用户找不到");
  93. }
  94. return View("Index", await _userManager.Users.ToListAsync());
  95. }
  96. }

UserXxViewModel

User 的各种视图模型,通过特性标注实现基本的验证和显式设置:

  1. public class UserCreateViewModel
  2. {
  3. [Required]
  4. [Display(Name = "用户名")]
  5. public string UserName { get; set; }
  6. [Required]
  7. [DataType(DataType.EmailAddress)]
  8. [RegularExpression(@"(?:[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*|""(?:[\x01-\x08\x0b\x0c\x0e-\x1f\x21\x23-\x5b\x5d-\x7f]|\\[\x01-\x09\x0b\x0c\x0e-\x7f])*"")@(?:(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?|\[(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?|[a-z0-9-]*[a-z0-9]:(?:[\x01-\x08\x0b\x0c\x0e-\x1f\x21-\x5a\x53-\x7f]|\\[\x01-\x09\x0b\x0c\x0e-\x7f])+)\])", ErrorMessage = "Email的格式不正确")]
  9. public string Email { get; set; }
  10. [Required]
  11. [DataType(DataType.Password)]
  12. public string Password { get; set; }
  13. [Required]
  14. [Display(Name = "身份证号")]
  15. [StringLength(18, MinimumLength = 18, ErrorMessage = "{0}的长度是{1}")]
  16. public string IdCard { get; set; }
  17. [Required]
  18. [Display(Name = "出生日期")]
  19. [DataType(DataType.Date)]
  20. public DateTime BirthDate { get; set; }
  21. }

扩展 IdentityUser

查看 IdentityUser 的源码,不难发现它的属性并不多。我们可以通过继承它来创建属性更丰富的 IdentityUser。

添加了身份证号和出生日期的 ApplicationUser:

  1. public class ApplicationUser:IdentityUser
  2. {
  3. [MaxLength(18)]
  4. public string IdCard { get; set; }
  5. [DataType(DataType.Date)]
  6. public DateTime BirthDate { get; set; }
  7. }

然后将 Configure Services 里面的代码:services.AddDefaultIdentity<IdentityUser> 修改为 services.AddDefaultIdentity<ApplicationUser>

然后修改 ApplicationDbContext 指明 IdentityUser 的实现类为 ApplicationUser:

  1. public class ApplicationDbContext : IdentityDbContext<ApplicationUser>
  2. {
  3. ...
  4. }

然后 Add-Migration + Update-Database 更新数据库。

最后将程序中所有原来使用 IdentityUser 的地方替换为 ApplicationUser。

自定义密码规则

Identity 默认要求用户设置复杂的强密码,我们可以通过 IdentityOptions 自定义密码规则。

  1. services.AddDefaultIdentity<ApplicationUser>(options =>
  2. {
  3. options.Password.RequireNonAlphanumeric = false;
  4. options.Password.RequireLowercase = false;
  5. options.Password.RequireUppercase = false;
  6. options.Password.RequiredLength = 6;
  7. })
  8. .AddDefaultUI(UIFramework.Bootstrap4)
  9. .AddEntityFrameworkStores<ApplicationDbContext>();