博客
关于我
Asp.Net Core之Identity应用(下篇)
阅读量:422 次
发布时间:2019-03-06

本文共 10274 字,大约阅读时间需要 34 分钟。

一、前言

在中简单介绍了 Asp.Net Core 自带的 Identity,一个负责对用户的身份进行认证的框架,当我们按需选择这个框架作为管理和存储我们应用中的用户账号数据的时候,就会添加到自己的项目当中去。这个时候,默认情况我们会使用自带的数据模型,但是考虑到需求的情况,我们可以通过自定义的方式更新数据模型,来达到我们的需求。

二、初识

在中我们完成了数据迁移加上项目的搭建,其中ApplicationDbContext是负责与Identity标识相关的用户,继承于IdentityDbContext上下文。当然了,我们发现根据这个上下文的扩展性,可以自定义用户数据,进行配置。

比如:自定义扩展的用户数据类来继承于IdentityUser类,更改用户数据模型属性,更改主键、更改表名列名等来满足我们的业务要求。

三、实践

接着上篇的WebIdentityDemoV3.1项目,将自定义用户数据添加到Identity DB,自定义扩展的用户数据类应继承IdentityUser类, 文件名为Areas / Identity / Data / {项目名称}User.cs。

3.1 表说明

这个就是我们要准备自定义的用户数据,本示例是直接继承于 Asp.Net Core 自带的 Identity的。

光从数据库表名上,我们就知道其中的含义了,就是用户角色管理。

数据说明:

_EFMigrationsHistory 是 Ef的迁移历史表。

AspNetUserClaimsAspNetRoleClaims是用户和角色的声明表,Claim在其中扮演者很重要的角色,甚至角色(Role)都被转换成了Claim,可以了解之前说到的模式。

AspNetUsersAspNetRolesAspNetUserRoles存储用户和角色信息。

AspNetUserTokens 用于外部验证的Token存储。

AspNetUserLogins 保留如 Google, Facebook, Twitter ,QQ等第三方登录的信息。

3.2 自定义模型

上下文用于通过两种方式配置模型:

  • 为泛型类型参数提供实体和键类型。
  • 重写 OnModelCreating 以修改这些类型的映射。

重写时 OnModelCreatingbase.OnModelCreating 应首先调用,然后调用重写配置。 EF Core 通常具有用于配置的最后一个 wins 策略。 例如,如果 ToTable 先使用一个表名称调用实体类型的方法,然后再使用另一个表名称再次调用该方法,则使用第二个调用中的表名。

3.3 自定义数据

这里以用户类进行举例说明:

3.3.1 自定义用户类

定义ApplicationUser类继承于IdentityUser用户数据类, 自定义类命名约定 {Application}User。

public class ApplicationUser:IdentityUser    {         ///         /// 用户编号        ///         public string UserNo { get; set; }        ///         /// 真实姓名        ///         public string UserTrueName { get; set; }    }

3.3.2 修改服务配置

将原来Startup文件中的ConfigureServices服务配置中的IdentityUser改成ApplicationUser

services.AddDefaultIdentity
(options => options.SignIn.RequireConfirmedAccount = true) .AddEntityFrameworkStores
();

改成:

services.AddDefaultIdentity
(options => options.SignIn.RequireConfirmedAccount = true) .AddEntityFrameworkStores
();

3.3.3 修改上下文

将原来ApplicationDbContext上下文继承于IdentityDbContext,改成IdentityDbContext<ApplicationUser>

原来的

public class ApplicationDbContext : IdentityDbContext{    public ApplicationDbContext(DbContextOptions
options) : base(options) { }}

改成:

ApplicationUser 类型用作上下文的泛型参数

public class ApplicationDbContext : IdentityDbContext
{ public ApplicationDbContext(DbContextOptions
options) : base(options) { }}

3.3.4 数据迁移

#1.存在数据库则先删除数据库#  Drop-Database (PMC) 或 dotnet ef database drop ( .NET Core CLI)#2.确认删除数据库后,删除迁移#  Remove-Migration (PMC) 或 dotnet ef migrations remove ( .NET Core CLI)# 再进行更新数据模型 ,添加迁移,转换成相应的数据库PM> Add-Migration CreateIdentitySchema2 -c ApplicationDbContext -o Data/MigrationsPM> Update-Database CreateIdentitySchema2

效果如下:

可以发现,有对应的自定义字段了。

3.3.5 更新替换

如果之前已经搭建好了项目,那么你需要将IdentityUser类改成自定义的ApplicationUser类。

更新 Pages/Shared/_LoginPartial ,并将替换 IdentityUserApplicationUser

@using Microsoft.AspNetCore.Identity@using WebApp1.Areas.Identity.Data@inject SignInManager
SignInManager@inject UserManager
UserManager

具体的其他替换修改方法就不说明演示了。

3.4 更改主键类型

在创建数据库之后更改PK列的数据类型在许多数据库系统上都存在问题。更改PK通常涉及删除和重新创建表。因此,在创建数据库时,应在初始迁移中指定PK类型。下面是更改主键类型步骤:

3.4.1 更改表主键类型

这里以ApplicationUser类为例,修改相关代码

// 用户表设置主键为Int    public class ApplicationUser : IdentityUser
{ ///
/// 用户编号 /// public string UserNo { get; set; } ///
/// 真实姓名 /// public string UserTrueName { get; set; } }

3.4.2 修改上下文

    public class ApplicationDbContext : IdentityDbContext
, Guid>

3.4.3 修改服务配置

  services.AddDefaultIdentity
(options => options.SignIn.RequireConfirmedAccount = true) .AddEntityFrameworkStores
();

3.4.4 数据迁移

#1.存在数据库则先删除数据库#  Drop-Database (PMC) 或 dotnet ef database drop ( .NET Core CLI)#2.确认删除数据库后,删除迁移#  Remove-Migration (PMC) 或 dotnet ef migrations remove ( .NET Core CLI)# 再进行更新数据模型 ,添加迁移,转换成相应的数据库PM> Add-Migration CreateIdentitySchema2 -c ApplicationDbContext -o Data/MigrationsPM> Update-Database CreateIdentitySchema2 

此时表的主键类型已修改完成,包括关系表的外键类型也同步更新了,

效果如下:  

3.5 更改表名和列名

3.5.1 更改表名

再更改表名之前,请先调用 base.OnModelCreating 。然后,添加配置覆盖默认表名,同时定义主键。这里的示例以将默认表名改为以tbl开头命名的表名

protected override void OnModelCreating(ModelBuilder builder)        {            var maxKeyLength = 256;            base.OnModelCreating(builder);            //自定义修改表名,以tbl命名开头            builder.Entity
(b => { b.ToTable("TblUsers"); }); builder.Entity
>(b => { //定义主键 b.HasKey(u => u.Id); b.ToTable("TblUserClaims"); }); builder.Entity
>(b => { b.HasKey(u => new { u.LoginProvider, u.ProviderKey }); b.ToTable("TblUserLogins"); }); builder.Entity
>(b => { b.HasKey(u => new { u.UserId, u.LoginProvider, u.Name }); b.ToTable("TblUserTokens"); }); builder.Entity
>(b => { b.HasKey(u => u.Id); b.ToTable("TblRoles"); }); builder.Entity
>(b => { b.HasKey(u => u.Id); b.ToTable("TblRoleClaims"); }); builder.Entity
>(b => { b.HasKey(u => new { u.UserId, u.RoleId }); b.ToTable("TblUserRoles"); }); } }

如果使用之类的应用类型 ApplicationUser ,请配置该类型而不是默认类型。

3.5.2 更改列名

下面的示例将更改某些列名,按需更改

protected override void OnModelCreating(ModelBuilder builder){    base.OnModelCreating(modelBuilder);    modelBuilder.Entity
(b => { b.Property(e => e.PasswordHash).HasColumnName("Password"); });}

3.5.3 更改长度

某些类型的数据库列可以配置某些 方面 (例如, string 允许) 最大长度。

protected override void OnModelCreating(ModelBuilder builder){    base.OnModelCreating(modelBuilder);    modelBuilder.Entity
(b => { b.Property(u => u.UserName).HasMaxLength(128); b.Property(u => u.NormalizedUserName).HasMaxLength(128); b.Property(u => u.Email).HasMaxLength(128); b.Property(u => u.NormalizedEmail).HasMaxLength(128); }); }

3.5.4 数据迁移

#进行更新数据模型 ,添加迁移,转换成相应的数据库PM> Add-Migration CreateIdentitySchema2 -c ApplicationDbContext -o Data/MigrationsPM> Update-Database CreateIdentitySchema2 

此时表的主键类型已修改完成,包括关系表的外键类型也同步更新了,

效果如下:  

3.6 初始化数据库

在创建项目时候,我们可以提前做好初始化数据的准备,将数据作为种子处理迁移到创建的数据库中进行初始化操作。

3.6.1 创建文件

创建SeedData.cs文件,用于初始化基础数据:

public class SeedData    {        public static void EnsureSeedData(IServiceProvider serviceProvider)        {            Console.WriteLine("Seeding database...");            using (var scope = serviceProvider.GetRequiredService
().CreateScope()) { var context = scope.ServiceProvider.GetService
(); context.Database.Migrate(); var userMgr = scope.ServiceProvider.GetRequiredService
>(); var alice = userMgr.FindByNameAsync("alice").Result; if (alice == null) { alice = new ApplicationUser { UserName = "alice" }; var result = userMgr.CreateAsync(alice, "Pass123$").Result; if (!result.Succeeded) { throw new Exception(result.Errors.First().Description); } result = userMgr.AddClaimsAsync(alice, new Claim[]{ new Claim(JwtClaimTypes.Name, "Alice Smith"), new Claim(JwtClaimTypes.GivenName, "Alice"), new Claim(JwtClaimTypes.FamilyName, "Smith"), new Claim(JwtClaimTypes.Email, "AliceSmith@email.com"), new Claim(JwtClaimTypes.EmailVerified, "true", ClaimValueTypes.Boolean), new Claim(JwtClaimTypes.WebSite, "http://alice.com") }).Result; if (!result.Succeeded) { throw new Exception(result.Errors.First().Description); } Console.WriteLine("alice created"); } else { Console.WriteLine("alice already exists"); } var bob = userMgr.FindByNameAsync("bob").Result; if (bob == null) { bob = new ApplicationUser { UserName = "bob" }; var result = userMgr.CreateAsync(bob, "Pass123$").Result; if (!result.Succeeded) { throw new Exception(result.Errors.First().Description); } result = userMgr.AddClaimsAsync(bob, new Claim[]{ new Claim(JwtClaimTypes.Name, "Bob Smith"), new Claim(JwtClaimTypes.GivenName, "Bob"), new Claim(JwtClaimTypes.FamilyName, "Smith"), new Claim(JwtClaimTypes.Email, "BobSmith@email.com"), new Claim(JwtClaimTypes.EmailVerified, "true", ClaimValueTypes.Boolean), new Claim(JwtClaimTypes.WebSite, "http://bob.com"), new Claim("location", "somewhere") }).Result; if (!result.Succeeded) { throw new Exception(result.Errors.First().Description); } Console.WriteLine("bob created"); } else { Console.WriteLine("bob already exists"); } } Console.WriteLine("Done seeding database."); Console.WriteLine(); } }

配置添加自定义用户信息和身份。

3.6.2 调用方法

然后我们可以从主入口Main方法调用它:

public static void Main(string[] args)        {            var seed = args.Contains("/seed");            if (seed)            {                args = args.Except(new[] { "/seed" }).ToArray();            }            var host = CreateHostBuilder(args).Build();            if (seed)            {                SeedData.EnsureSeedData(host.Services);            }            host.Run();        }

3.6.3 程序运行

输入 dotnet run /seed 

3.6.4 效果

总结

  1. 本篇简单介绍了对Identity自定义用户以及表结构说明,以及根据自定义更改生成模型,并添加到示例项目当中。
  2. 后续会将此身份认证机制来应用到IdentityServer4中使用,进行用户角色管理存储操作。
  3. 如果有不对的或不理解的地方,希望大家可以多多指正,提出问题,一起讨论,不断学习,共同进步。

附加

转载地址:http://egruz.baihongyu.com/

你可能感兴趣的文章
go等待N个线程完成操作总结
查看>>
ReactJs入门教程-精华版
查看>>
Python 之网络式编程
查看>>
MySql5.5安装步骤及MySql_Front视图配置
查看>>
mybatis绑定错误-- Invalid bound statement (not found)
查看>>
python去除字符串中的特殊字符(爬虫存储数据时会遇到不能作为文件名的字符串)
查看>>
SpringCloud微服务(03):Hystrix组件,实现服务熔断
查看>>
云计算之路-阿里云上:0:25~0:40网络存储故障造成网站不能正常访问
查看>>
网站故障公告1:使用阿里云RDS之后一个让人欲哭无泪的下午
查看>>
上周热点回顾(8.12-8.18)
查看>>
蹒跚来迟:新版博客后台上线公测
查看>>
[网站公告]又拍云API故障造成图片无法上传(已恢复)
查看>>
上周热点回顾(6.9-6.15)
查看>>
.NET跨平台之旅:借助ASP.NET 5 Beta5的新特性显示CLR与操作系统信息
查看>>
上周热点回顾(7.27-8.2)
查看>>
上周热点回顾(5.9-5.15)
查看>>
上周热点回顾(1.16-1.22)
查看>>
上周热点回顾(1.23-1.29)
查看>>
云计算之路-阿里云上:14:20-14:55博客后台2台服务器都CPU 100%引发的故障
查看>>
【故障公告】10:30-10:45 左右 docker swarm 集群节点问题引发故障
查看>>