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 & ...
随机推荐
- LeetCode——Customers Who Never Order(灵活使用NOT IN以及IN)
Suppose that a website contains two tables, the Customers table and the Orders table. Write a SQL qu ...
- SQL的概念与发展 - 极客时间学习笔记
了解SQL SQL的两个重要标准是SQL92和SQL99. SQL语言的划分 DDL,也叫Data Definition Language,也就是数据定义语言,用来定义数据库对象,包括数据库.数据表和 ...
- 8.InfluxDB-InfluxQL基础语法教程--ORDER BY子句
本文翻译自官网,官网地址:(https://docs.influxdata.com/influxdb/v1.7/query_language/data_exploration/) 在InfluxDB中 ...
- Django之 数据库ORM
一.ORM Django的 业务 少不了 跟数据库打交道,不然没有数据库保存一些数据将是一件很糟糕的事情.Django 对 数据库 支持原生的 SQL语句,但更好的对数据库支持,Django自己有一套 ...
- if语句编写Mysql备份脚本
#!/bin/bash #auto bakcup mysql db #by authors zgh #define backup path BAK_DIR=/data/backup/`date +%Y ...
- Rust的多线程程序
一定要用闭包? 感觉有点过了. use std::thread; use std::time::Duration; fn main() { let v = vec![, , ]; let handle ...
- oracle_day1
本节内容: 1:oracle的服务 2:oracle 11 G 的新功能 3:数据库的三大范式 1:oracle的服务 安装完oracle 想要使用oracle 必须要启动的两个服务. 要是还想要使用 ...
- python SSL 错误
python 使用pip 安装模块是提示SSL错误 出现该问题的原因由于系统的openssl是1.0.1的版本,对于python3.7太老了,需要更新为openssl1.0.2或者libressl2. ...
- CSS中的父相子绝布局
主要应用场景,就是我想要块的布局根据父级来定位,而不是根据页面. 例如,下面的例子中,我用两个半圆拼成一个正圆,思路是用一个父级标签把两个子标签包起来,父标签是一个正圆,然后子标签各占一半,先化成两个 ...
- 四则运算web版需求规格说明书
目录 1引言... 4 1.1 目的... 4 1.2 背景... 4 1.3 术语... 4 1.4 预期读者与阅读建议... 5 1.5 参考资料... 6 1.6 需求描述约定... ...