asp.net core系列 47 Identity 自定义用户数据
一.概述
接着上篇的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 = ;
options.Password.RequiredUniqueChars = ; // Lockout settings.
options.Lockout.DefaultLockoutTimeSpan = TimeSpan.FromMinutes();
options.Lockout.MaxFailedAccessAttempts = ;
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(); 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(, ErrorMessage = "The {0} must be at least {2} and at max {1} characters long.", MinimumLength = )]
[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 自定义用户数据的更多相关文章
- 【asp.net core 系列】15 自定义Identity
0. 前言 在之前的文章中简单介绍了一下asp.net core中的Identity,这篇文章将继续针对Identity进行进一步的展开. 1. 给Identity添加额外的信息 在<[asp. ...
- asp.net core系列 48 Identity 身份模型自定义
一.概述 ASP.NET Core Identity提供了一个框架,用于管理和存储在 ASP.NET Core 应用中的用户帐户. Identity添加到项目时单个用户帐户选择作为身份验证机制. 默认 ...
- asp.net core系列 46 Identity介绍
一. Identity 介绍 ASP.NET Core Identity是一个会员系统,可为ASP.NET Core应用程序添加登录功能.可以使用SQL Server数据库配置身份以存储用户名,密码和 ...
- asp.net core系列 52 Identity 其它关注点
一.登录分析 在使用identity身份验证登录时,在login中调用的方法是: var result = await _signInManager.PasswordSignInAsync(Input ...
- asp.net core利用DI实现自定义用户系统,脱离ControllerBase.User
前言 很多时候其实我们并不需要asp.net core自带的那么复杂的用户系统,基于角色,各种概念,还得用EF Core,而且在web应用中都是把信息存储到cookie中进行通讯(我不喜欢放cooki ...
- asp.net core系列 49 Identity 授权(上)
一.概述 授权是指用户能够访问资源的权限,如页面数据的查看.编辑.新增.删除.导出.下载等权限.ASP.NET Core 授权提供了多种且灵活的方式,包括:Razor pages授权约定.简单授权.R ...
- asp.net core系列 51 Identity 授权(下)
1.6 基于资源的授权 前面二篇中,熟悉了五种授权方式(对于上篇讲的策略授权,还有IAuthorizationPolicyProvider的自定义授权策略提供程序没有讲,后面再补充).本篇讲的授权方式 ...
- asp.net core系列 50 Identity 授权(中)
1.5 基于策略的授权 在上篇中,已经讲到了授权访问(authorization)的四种方式.其中Razor Pages授权约定和简单授权二种方式更像是身份认证(authentication) ,因为 ...
- 【目录】asp.net core系列篇
随笔分类 - asp.net core系列篇 asp.net core系列 68 Filter管道过滤器 摘要: 一.概述 本篇详细了解一下asp.net core filters,filter叫&q ...
随机推荐
- UE4学习心得:Scene Component蓝图的一个简单应用
Scene Component是蓝图类中一个不怎么常用的分类(特别是对于新手而言),主要是其实现的功能可以在Actor类中用相同的方法实现,使其作用显得有点多余. 笔者在使用过这个类之后发现其作用更相 ...
- textarea 里设置 style="resize:none"
禁止textarea拉伸的方法是:: 设置这个 style="resize:none" 属性 例子: < ...
- activiti工作流框架简介
常见的工作流框架:activiti, JBPM, OSWorkflow activiti框架基于23张基础的表数据, 基于Mybatis操作数据库. JBPM框架基于18张基础的表数据, 基于hibe ...
- maven 编译出错Fatal error compiling: 无效的目标发行版: 1.8 -> [Help 1] 解决办法
这几天在为公司项目搭建一个后台框架,使用的是eclipse-Mars自带的maven插件,在maven进行编译的时候,出现Fatal error compiling: 无效的目标发行版: 1.8 -& ...
- Java如何获取系统信息(包括操作系统、jvm、cpu、内存、硬盘、网络、io等)
1 下载安装sigar-1.6.4.zip 使用java自带的包获取系统数据,容易找不到包,尤其是内存信息不够准确,所以选择使用sigar获取系统信息. 下载地址:http://sourceforge ...
- 关于Linux虚拟化技术KVM的科普 科普五(From 世民谈云计算)
另一位大神写到KVM文章,KVM 介绍(1):简介及安装.KVM 介绍(2):CPU 和内存虚拟化.KVM 介绍(3):I/O 全虚拟化和准虚拟化 [KVM I/O QEMU Full-Virtual ...
- 小程序开发之图片转Base64(C#、.et)
小程序页面代码因为某些人力不可控的代码丢失了,这里简单说明一下 调用小程序APIwx.chooseImage(OBJECT)选择相册或拍摄照片,会返回 tempFilePaths,之后通过wx.upl ...
- SQLMap入门之在Windows上安装SQLMap
前言: SQLMap是一个开放源代码的sql注入工具,SQLMap是使用Python语言开发成的,他的运行需要有Python环境的支持.写这篇文章时我使用的SQLMap版本是"sqlmap- ...
- 阿里云和腾讯云免费SSL证书 专题
阿里云部署SSL证书 http://www.cnblogs.com/sslwork/p/5984167.html 查找中间证书 为了确保兼容到所有浏览器,我们必须在阿里云上部署中间证书,如果不部署证书 ...
- 浅谈服务间通信【MQ在分布式系统中的使用场景】
解决的问题 一项技术的产生必然是为了解决问题而生,了解了一项技术解决的问题,就能够很轻松的理解这项技术的设计根本,从而更好地理解与使用这项技术. 消息中间件和RPC从根本上来说都是为了解决分布式系统的 ...