美文网首页工作生活
asp.net core系列 47 Identity 自定义用户

asp.net core系列 47 Identity 自定义用户

作者: 懒懒的程序员一枚 | 来源:发表于2019-07-02 14:16 被阅读0次

    一.概述

    接着上篇的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
    
    image
    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 页,已经可以下载和删除用户数据


    参考文献

    自定义用户数据

    相关文章

      网友评论

        本文标题:asp.net core系列 47 Identity 自定义用户

        本文链接:https://www.haomeiwen.com/subject/vrmzcctx.html