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 & ...
随机推荐
- 网络唤醒(WOL)全解指南:原理篇【转】
转自:https://blog.csdn.net/z5859095/article/details/82819075 什么是网络唤醒网络唤醒(Wake-on-LAN,WOL)是一种计算机局域网唤醒技术 ...
- 其他综合-CentOS 7 命令行显示优化
CentOS 7 命令行显示优化 1.实验描述 通过 CentOS 7.6 的显示优化,为实现命令行显示提供良好视觉体验. [基于此文章的环境]点我快速打开文章 2.实验环境 使用软件的版本:VMwa ...
- Django类
django 1.中间件 中间件一般做认证或批量请求处理,django中的中间件,其实是一个类,在请求和结束后,django会根据自己的规则在合适的时机执行中间件中相应的方法, 如请求过来 执行p ...
- 关于苹果macOS更新到Catalina后出现的各种问题(持续更新)
一.Mac系统更新后 Git 不能用,提示 missing xcrun at:xxx xcrun: error: invalid active developer path (/Library/Dev ...
- 8-剑指offer: 替换空格
题目描述 请实现一个函数,将一个字符串中的每个空格替换成"%20".例如,当字符串为We Are Happy.则经过替换之后的字符串为We%20Are%20Happy. 代码: c ...
- maven配置阿里云国内仓库
<mirror> <id>alimaven</id> <name>aliyun maven</name> <url>http:/ ...
- P256 VRF实现解读
目录 P256 VRF实现及其改造 公式推导 H1:把任意信息映射到曲线上的点 H2: 映射任意信息为(1,q) 计算随机数 随机数的proof 如何验证 VRF优点 针对S256曲线的改造 1. 使 ...
- JS闭包—你不知道的JavaScript上卷读书笔记(二)
关于闭包,初学者会被绕的晕头转向,在学习的路上也付出了很多精力来理解. 让我们一起来揭开闭包神秘的面纱. 闭包晦涩的定义 看过很多关于闭包的定义,很多讲的云里雾里,晦涩难懂.让不少人以为闭包是多么玄乎 ...
- nginx配置代理时参数说明
- SpringBootThymeleaf案例
一.添加依赖 <!-- 添加thymeleaf模版的依赖 --> <dependency> <groupId>org.springframework.boot< ...