一. 概述
接着上篇的 webAppIdentityDemo 项目, 将自定义用户数据添加到 Identity DB, 自定义扩展的用户数据类应继承 IdentityUser 类, 文件名为 Areas / Identity / Data / {项目名称}User.cs. 自定义的用户数据模型属性需要使用 [PersonalData] 来修饰, 以便自动下载和删除. 使数据能够下载和删除有助于满足 GDPR 要求.
1.1 自定义用户数据类 WebAppIdentityDemo.Areas.Identity.Data.
- public class WebAppIdentityDemoUser:IdentityUser
- {
- /// <summary>
- /// Full name
- /// </summary>
- [PersonalData]
- public string Name { get; set; }
- /// <summary>
- /// Birth Date
- /// </summary>
- [PersonalData]
- public DateTime DOB { get; set; }
- }
使用属性修饰 PersonalData 特性是:
使用 Areas/Identity/Pages/Account/Manage/DeletePersonalData.cshtml 页调用 UserManager.Delete
使用 Areas/Identity/Pages/Account/Manage/DownloadPersonalData.cshtml 页下载用户数据
1.2 修改 IdentityHostingStartup
将 Startup 中有关 identity 的服务移到该文件中, 好集中管理.
- public class IdentityHostingStartup : IHostingStartup
- {
- public void Configure(IWebHostBuilder builder)
- {
- builder.ConfigureServices((context, services) => {
- services.AddDbContext<ApplicationDbContext>(options =>
- options.UseSqlServer(
- context.Configuration.GetConnectionString("DefaultConnection")));
- services.AddDefaultIdentity<WebAppIdentityDemoUser>()
- .AddDefaultUI()
- .AddEntityFrameworkStores<ApplicationDbContext>();
- services.Configure<IdentityOptions>(options =>
- {
- // Password settings.
- options.Password.RequireDigit = true;
- options.Password.RequireLowercase = true;
- options.Password.RequireNonAlphanumeric = true;
- options.Password.RequireUppercase = true;
- options.Password.RequiredLength = 6;
- options.Password.RequiredUniqueChars = 1;
- // Lockout settings.
- options.Lockout.DefaultLockoutTimeSpan = TimeSpan.FromMinutes(5);
- options.Lockout.MaxFailedAccessAttempts = 5;
- options.Lockout.AllowedForNewUsers = true;
- // User settings.
- options.User.AllowedUserNameCharacters =
- "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789-._@+";
- options.User.RequireUniqueEmail = false;
- });
- services.ConfigureApplicationCookie(options =>
- {
- // Cookie settings
- options.Cookie.HttpOnly = true;
- options.ExpireTimeSpan = TimeSpan.FromMinutes(5);
- options.LoginPath = $"/Identity/Account/Login";
- options.LogoutPath = $"/Identity/Account/Logout";
- options.AccessDeniedPath = $"/Identity/Account/AccessDenied";
- });
- });
- }
- }
1.3 修改 DbContext 上下文
- // public class ApplicationDbContext : IdentityDbContext
- public class ApplicationDbContext : IdentityDbContext<WebAppIdentityDemoUser>
- {
- public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options)
- : base(options)
- {
- }
- protected override void OnModelCreating(ModelBuilder builder)
- {
- base.OnModelCreating(builder);
- // Customize the ASP.NET Core Identity model and override the defaults if needed.
- // For example, you can rename the ASP.NET Core Identity table names and more.
- // Add your customizations after calling base.OnModelCreating(builder);
- }
- }
1.4 数据库版本迁移
- PM> Add-Migration IdentitySchema2
- PM> Update-Database IdentitySchema2
1.5 更新注册页面
在开发中, 会员系统要重用修改的页面, 把 IdentityUser 改成 WebAppIdentityDemoUser. 如果没改将报错: 未解析到服务 IdentityUser. 红色部分为修改的代码
- [AllowAnonymous]
- public class RegisterModel : PageModel
- {
- // private readonly SignInManager<IdentityUser> _signInManager;
- //private readonly UserManager<IdentityUser> _userManager;
- private readonly SignInManager<WebAppIdentityDemoUser> _signInManager;
- private readonly UserManager<WebAppIdentityDemoUser> _userManager;
- private readonly ILogger<RegisterModel> _logger;
- private readonly IEmailSender _emailSender;
- public RegisterModel(
- UserManager<WebAppIdentityDemoUser> userManager,
- SignInManager<WebAppIdentityDemoUser> signInManager,
- ILogger<RegisterModel> logger,
- IEmailSender emailSender)
- {
- _userManager = userManager;
- _signInManager = signInManager;
- _logger = logger;
- _emailSender = emailSender;
- }
- [BindProperty]
- public InputModel Input { get; set; }
- public string ReturnUrl { get; set; }
- public class InputModel
- {
- [Required]
- [DataType(DataType.Text)]
- [Display(Name = "Full name")]
- public string Name { get; set; }
- [Required]
- [Display(Name = "Birth Date")]
- [DataType(DataType.Date)]
- public DateTime DOB { get; set; }
- [Required]
- [EmailAddress]
- [Display(Name = "Email")]
- public string Email { get; set; }
- [Required]
- [StringLength(100, ErrorMessage = "The {0} must be at least {2} and at max {1} characters long.", MinimumLength = 6)]
- [DataType(DataType.Password)]
- [Display(Name = "Password")]
- public string Password { get; set; }
- [DataType(DataType.Password)]
- [Display(Name = "Confirm password")]
- [Compare("Password", ErrorMessage = "The password and confirmation password do not match.")]
- public string ConfirmPassword { get; set; }
- }
- public void OnGet(string returnUrl = null)
- {
- ReturnUrl = returnUrl;
- }
- public async Task<IActionResult> OnPostAsync(string returnUrl = null)
- {
- returnUrl = returnUrl ?? Url.Content("~/");
- if (ModelState.IsValid)
- {
- // var user = new IdentityUser { UserName = Input.Email, Email = Input.Email };
- var user = new WebAppIdentityDemoUser
- {
- UserName = Input.Email,
- Email = Input.Email,
- Name = Input.Name,
- DOB = Input.DOB
- };
- var result = await _userManager.CreateAsync(user, Input.Password);
- if (result.Succeeded)
- {
- _logger.LogInformation("User created a new account with password.");
- var code = await _userManager.GenerateEmailConfirmationTokenAsync(user);
- var callbackUrl = Url.Page(
- "/Account/ConfirmEmail",
- pageHandler: null,
- values: new { userId = user.Id, code = code },
- protocol: Request.Scheme);
- await _emailSender.SendEmailAsync(Input.Email, "Confirm your email",
- $"Please confirm your account by <a href='{HtmlEncoder.Default.Encode(callbackUrl)}'>clicking here</a>.");
- await _signInManager.SignInAsync(user, isPersistent: false);
- return LocalRedirect(returnUrl);
- }
- foreach (var error in result.Errors)
- {
- ModelState.AddModelError(string.Empty, error.Description);
- }
- }
- // If we got this far, something failed, redisplay form
- return Page();
- }
- }
- @page
- @model RegisterModel
- @{
- ViewData["Title"] = "Register";
- }
- <h1>@ViewData["Title"]</h1>
- <div class="row">
- <div class="col-md-4">
- <form asp-route-returnUrl="@Model.ReturnUrl" method="post">
- <h4>Create a new account.</h4>
- <hr />
- <div asp-validation-summary="All" class="text-danger"></div>
- <div class="form-group">
- <label asp-for="Input.Name"></label>
- <input asp-for="Input.Name" class="form-control" />
- <span asp-validation-for="Input.Name" class="text-danger"></span>
- </div>
- <div class="form-group">
- <label asp-for="Input.DOB"></label>
- <input asp-for="Input.DOB" class="form-control" />
- <span asp-validation-for="Input.DOB" class="text-danger"></span>
- </div>
- <div class="form-group">
- <label asp-for="Input.Email"></label>
- <input asp-for="Input.Email" class="form-control" />
- <span asp-validation-for="Input.Email" class="text-danger"></span>
- </div>
- <div class="form-group">
- <label asp-for="Input.Password"></label>
- <input asp-for="Input.Password" class="form-control" />
- <span asp-validation-for="Input.Password" class="text-danger"></span>
- </div>
- <div class="form-group">
- <label asp-for="Input.ConfirmPassword"></label>
- <input asp-for="Input.ConfirmPassword" class="form-control" />
- <span asp-validation-for="Input.ConfirmPassword" class="text-danger"></span>
- </div>
- <button type="submit" class="btn btn-primary">Register</button>
- </form>
- </div>
- </div>
- @section Scripts {
- <partial name="_ValidationScriptsPartial" />
- }
启动程序, 运行注册页, 保存成功后, 查看数据库, 如下所示:
1.6 其它相关页修改
下面这些最基本的页面, 都需要把 IdentityUser 改成 WebAppIdentityDemoUser.
登录页 /Identity/Account/Login
注册页 Identity/Account/Register
会员管理后台主页 /Identity/Account/Manage/index
个人资料页 /Identity/Account/Manage/PersonalData
个人资料删除 /Identity/Account/Manage/DeletePersonalData
个人资料下载 / Identity/Account/Manage/ DownloadPersonalData.cshtml
分部页 _ManageNav.cshtml
下面是 Account/Manage/Index.cshtml 页, 已经加上自定义的二个用户字段信息, 具体更新代码见官网
下面是 / Identity/Account/Manage/PersonalData.cshtml 页, 已经可以下载和删除用户数据
参考文献
自定义用户数据
来源: https://www.cnblogs.com/MrHSR/p/10578369.html