AspNetCore.Identity详解2——注册用户
上一篇:AspNetCore.Identity详解1——入门使用
打开数据库,可以看到使用EF自动生成的表结构如下:

重点关注AspNetUsers表,打开数据库里的表可以知道目前也只用到了这张表。然后下载asp.net core开源代码 。在我们创建的项目里并没有/Identity/Account/Register 页面,可以猜测登录注册的页面必然封装在Microsoft.AspNetCore.Identity 里面。
<form asp-controller="Account" asp-action="Register" asp-route-returnurl="@ViewData["ReturnUrl"]" method="post" class="form-horizontal" role="form">
略......
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<button type="submit" class="btn btn-default">Register</button>
</div>
</div>
</form>
找到Account/Register 的post方法:
[HttpPost]
[AllowAnonymous]
[ValidateAntiForgeryToken]
public async Task<IActionResult> Register(RegisterViewModel model, string returnUrl = null)
{
ViewData["ReturnUrl"] = returnUrl;
if (ModelState.IsValid)
{
var user = new ApplicationUser { UserName = model.Email, Email = model.Email };
var result = await _userManager.CreateAsync(user, model.Password);
if (result.Succeeded)
{
// For more information on how to enable account confirmation and password reset please visit http://go.microsoft.com/fwlink/?LinkID=532713
// Send an email with this link
//var code = await _userManager.GenerateEmailConfirmationTokenAsync(user);
//var callbackUrl = Url.Action("ConfirmEmail", "Account", new { userId = user.Id, code = code }, protocol: HttpContext.Request.Scheme);
//await _emailSender.SendEmailAsync(model.Email, "Confirm your account",
// "Please confirm your account by clicking this link: <a href=\"" + callbackUrl + "\">link</a>");
await _signInManager.SignInAsync(user, isPersistent: false);
_logger.LogInformation(, "User created a new account with password.");
return RedirectToLocal(returnUrl);
}
AddErrors(result);
}
// If we got this far, something failed, redisplay form
return View(model);
}
这一行代码会帮我们完成注册任务
var result = await _userManager.CreateAsync(user, model.Password);
查看user 实体的定义
public class ApplicationUser : IdentityUser
{
}
public class IdentityUser : IdentityUser<string>
{
public IdentityUser()
{
Id = Guid.NewGuid().ToString();
SecurityStamp = Guid.NewGuid().ToString();
}
public IdentityUser(string userName) : this()
{
UserName = userName;
}
}
public class IdentityUser<TKey> where TKey : IEquatable<TKey>
{
public IdentityUser() { }
public IdentityUser(string userName) : this()
{
UserName = userName;
}
[PersonalData]
public virtual TKey Id { get; set; }
[ProtectedPersonalData]
public virtual string UserName { get; set; }
public virtual string NormalizedUserName { get; set; }
[ProtectedPersonalData]
public virtual string Email { get; set; }
public virtual string NormalizedEmail { get; set; }
[PersonalData]
public virtual bool EmailConfirmed { get; set; }
public virtual string PasswordHash { get; set; }
public virtual string SecurityStamp { get; set; }
public virtual string ConcurrencyStamp { get; set; } = Guid.NewGuid().ToString();
[ProtectedPersonalData]
public virtual string PhoneNumber { get; set; }
[PersonalData]
public virtual bool PhoneNumberConfirmed { get; set; }
[PersonalData]
public virtual bool TwoFactorEnabled { get; set; }
public virtual DateTimeOffset? LockoutEnd { get; set; }
public virtual bool LockoutEnabled { get; set; }
public virtual int AccessFailedCount { get; set; }
public override string ToString()
=> UserName;
}
打开CreateAsync方法,可以看到经过三步完成用户注册
public virtual async Task<IdentityResult> CreateAsync(TUser user, string password)
{
ThrowIfDisposed();
var passwordStore = GetPasswordStore();
if (user == null)
{
throw new ArgumentNullException(nameof(user));
}
if (password == null)
{
throw new ArgumentNullException(nameof(password));
}
var result = await UpdatePasswordHash(passwordStore, user, password);
if (!result.Succeeded)
{
return result;
}
return await CreateAsync(user);
}
逐个查看注释1,2,3的方法
private IUserPasswordStore<TUser> GetPasswordStore()
{
var cast = Store as IUserPasswordStore<TUser>;
if (cast == null)
{
throw new NotSupportedException(Resources.StoreNotIUserPasswordStore);
}
return cast;
}
GetPasswordStore()方法会返回IUserPasswordStore<TUser>接口,Store 这个变量是什么呢?是IUserStore<TUser>,让人困惑的是IUserPasswordStore<TUser>继承了IUserStore<TUser>,
为什么Store可以转换为自己的子类呢?找到UserStoreBase类,看到它继承了IUserPasswordStore接口,由此可以猜测Store是UserStoreBase的实例。
// TUser是ApplicationUser
//protected internal IUserStore<ApplicationUser> Store { get; set; }
protected internal IUserStore<TUser> Store { get; set; }
第二步,完成了对密码的加密工作,同时更新了用户的安全戳(就是一个随机生成的字符串)
private async Task<IdentityResult> UpdatePasswordHash(IUserPasswordStore<TUser> passwordStore,
TUser user, string newPassword, bool validatePassword = true)
{
if (validatePassword)
{
var validate = await ValidatePasswordAsync(user, newPassword);
if (!validate.Succeeded)
{
return validate;
}
}
var hash = newPassword != null ? PasswordHasher.HashPassword(user, newPassword) : null;
await passwordStore.SetPasswordHashAsync(user, hash, CancellationToken);
await UpdateSecurityStampInternal(user);
return IdentityResult.Success;
}
第三步:完成对用户的最终创建
public virtual async Task<IdentityResult> CreateAsync(TUser user)
{
ThrowIfDisposed();
await UpdateSecurityStampInternal(user);
var result = await ValidateUserAsync(user);
if (!result.Succeeded)
{
return result;
}
if (Options.Lockout.AllowedForNewUsers && SupportsUserLockout)
{
await GetUserLockoutStore().SetLockoutEnabledAsync(user, true, CancellationToken);
}
await UpdateNormalizedUserNameAsync(user);
await UpdateNormalizedEmailAsync(user);
return await Store.CreateAsync(user, CancellationToken);
}
找到UserOnlyStore类,这里面有最后一步向数据库插入用户的操作。
整个过程很绕,在理清逻辑的过程中很容易迷失。如果想要避免迷失,一定要牢记我们只是想看看注册用户这一步是怎样完成的,千万不要关心与之无关的代码。
AspNetCore.Identity详解2——注册用户的更多相关文章
- AspNetCore.Identity详解1——入门使用
今年在面试的时候被问到单点登录的知识,当时支支吾吾不知该如何作答,于是面试失败.回到住所便开始上网查找资料,但苦于难于找到详尽的demo,总是无法入门.又由于我正在学习了解asp.net core,里 ...
- CEPH-2:rbd功能详解及普通用户应用ceph集群
ceph集群rbd使用详解 一个完整的ceph集群,可以提供块存储.文件系统和对象存储. 本节主要介绍rbd存储功能如何灵活的使用,集群背景: $ ceph -s cluster: id: 53717 ...
- ASP.NET Core 中 HttpContext 详解与使用 | Microsoft.AspNetCore.Http 详解 (转载)
“传导体” HttpContext 要理解 HttpContext 是干嘛的,首先,看图 图一 内网访问程序 图二 反向代理访问程序 ASP.NET Core 程序中,Kestrel 是一个基于 li ...
- ASP.NET Identity详解
Asp.Net Identiy是ASP.NET身份验证机制. 如何构建安全的Web应用? 我们先来思考一个问题:如何构建安全的WEB应用? 一直以来,这都是比较热门的话题.不幸的是,目前还没有一种 ...
- ASP.NET Core 中 HttpContext 详解与使用 | Microsoft.AspNetCore.Http 详解
笔者没有学 ASP.NET,直接学 ASP.NET Core ,学完 ASP.NET Core MVC 基础后,开始学习 ASP.NET Core 的运行原理.发现应用程序有一个非常主要的 “传导体” ...
- 详解Windows注册表分析取证
大多数都知道windows系统中有个叫注册表的东西,但却很少有人会去深入的了解它的作用以及如何对它进行操作.然而对于计算机取证人员来说注册表无疑是块巨大的宝藏.通过注册表取证人员能分析出系统发生了什么 ...
- 详解MySQL的用户密码过期功能
这篇文章主要为大家详细介绍了MySQL的用户密码过期功能的相关资料,需要的朋友可以参考下 Payment Card Industry,即支付卡行业,PCI行业表示借记卡.信用卡.预付卡.电子钱包. ...
- 详解Oracle创建用户权限全过程
本文将介绍的是通过创建一张表,进而实现Oracle创建用户权限的过程.以下这些代码主要也就是为实现Oracle创建用户权限而编写,希望能对大家有所帮助. 注意:每条语语分开执行,结尾必须用分号; // ...
- 详解管理root用户权限的sudo服务程序
在你想要使用超级权限临时运行一条命令时,sudo 命令非常方便,但是当它不能如你期望的工作时,你也会遇到一些麻烦.比如说你想在某些日志文件结尾添加一些重要的信息,你可能会尝试这样做: $ echo & ...
随机推荐
- RDD算子的使用
TransformationDemo.scala import org.apache.spark.{HashPartitioner, SparkConf, SparkContext} import s ...
- netcore2.2以及netcore3.0下的swagger使用
自从core3.0发布后,中间有很多东西跟以往用到的2.2版本相差特别多,今天主要来说一下swagger不同版本下的使用. swagger就是一个可视化接口工具,为了方便让调用者能够很好的了解接口以及 ...
- React 受控组件和非受控组件
需求用户名自动获取 onChange用户状态发生改变 就获取值 就是时时获取值 使用onChange 点击按钮 获取密码 只要绑定了点击事件 就可以获取值 通过 let usercont=event. ...
- BeanShell实现加密解密功能
一,在IDEA中写好加密的脚本 二,然后将整个包文件导出,生成jar包 三,将jar包文件放到jmeter的lib/ext目录下 然后在jmeter的BeanShell中引入该类,调用其中的加密方法 ...
- 201871010107-公海瑜《面向对象程序设计(java)》第七周学习总结
201871010107-公海瑜<面向对象程序设计(java)>第七周学习总结 项目 内容 这个作业属于哪个课程 ...
- Docker安装(二)
一.前提条件 目前,CentOS 仅发行版本中的内核支持 Docker. Docker 运行在 CentOS 7 上,要求系统为64位.系统内核版本为 3.10 以上. Docker 运行在 Cent ...
- Eclipse安装svn插件(五)
一.在线安装 1. 点击 Help --> Install New Software... 2. 在弹出的窗口中点击add按钮,输入Name(任意)和Location(插件的URL),点击OK ...
- 百度PaddlePaddle:
百度正式发布PaddlePaddle深度强化学习框架PARL 近日,百度PaddlePaddle正式发布了深度强化学习框架 PARL,同时开源了基于该框架的.在 NeurIPS 2018 强化学习赛事 ...
- 高效Redis工具类
一.引言 本篇博客以redis缓存为主.至于什么是redis缓存?还有没有其它的缓存?哪个缓存的性能会更好?这里就不一一做介绍了!(有兴趣的可以自己去百度一下) 在日常的开发中,我们或多或少(必须)的 ...
- [清华集训2017]小 Y 和地铁(神奇思路,搜索,剪枝,树状数组)
世界上最不缺的就是好题. 首先考虑暴搜.(还有什么题是从这东西推到正解的……) 首先单独一个换乘站明显没用,只用考虑一对对的换乘站. 那么有八种情况:(从题解偷图) 然后大力枚举每个换 ...