1. Overview
ASP.NET Core Identity provides a framework for managing and storing user accounts in ASP.NET Core applications. Individual user accounts are selected as the authentication mechanism when Identity is added to a project. By default, Identity can use the Entity Framework (EF) Core data model. This article describes how to customize the identity model.
1.1 The following is the existing identity model, which consists of the following entity types:
Entity Type |
Description |
Relationship |
Users (user table) | Login user | |
Roles (role table) |
Role |
|
UserClaims (User Claim Form ) | Permissions owned by users | Every Users has Multiple UserClaims |
UserTokens | User’s authentication token | Multiple UserTokens for each Users |
UserLogins | Associate users with logins. | Each Users has multiple UserLogins |
RoleClaims (role declaration table) | Permissions owned by the role | Every Each Roles has multiple RoleClaims |
UserRoles | User and role association | Each Users has multiple Roles |
(1) Users table
Field name |
Field Type |
Description |
Id | Guid | Primary key, the default is Guid |
UserName | Nvarchar(256) | Username or email |
NormalizedUserName | Nvarchar(256) | Normalization Username, converted to uppercase |
Nvarchar (256) | ||
NormalizedEmail | Nvarchar(256) | Normalized mailbox name, converted to uppercase |
EmailConfirmed | bit | Verification email confirmation, the default is false |
PasswordHash | Nvarchar(max) | Password Hash |
SecurityStamp | Nvarchar(max) | Security mark, Guid type, generate random when user credentials change Value, such as changing username |
ConcurrencyStamp | Nvarchar( max) | Synchronization tag, Guid type |
PhoneNumber | Nvarchar(max) | Telephone |
PhoneNumberConfirmed | bit> | Phone Confirm |
TwoFactorEnabled | bit | Two-factor authentication |
LockoutEnd | datetimeoffset(7) | The expiration date of the lock, null means no lock |
LockoutEnabled | bit | Whether it can be Lock |
AccessFailedCount | int | Number of failed login attempts to determine whether to lock the user |
1.2 Default model configuration
Identity defines a number of context classes that inherit from DbContext to configure and use the model. This configuration is done using the EF Core Code First Fluent API in the OnModelCreating method of the context class. For the default model structure, you can view the Migration file and the model relationship ModelSnapshot file, but if you want to modify the model, do not change it here. Below is the AspNetUsers model code:
The following is the data table and relationships generated by the default model:
2. Model customization
When rewriting the OnModelCreating
method
in the EF context, the base.OnModelCreating
method
is called first; then rewrite will override the default model configuration.
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); } }
2.1 Custom user data
We talked about custom user data in the previous article, here is a summary. Custom user data is supported by inheriting the IdentityUser class. Custom class naming convention {Application}User.
//Define {Application}User extension class to implement the user model public class WebAppIdentityDemoUser : IdentityUser //Using {Application}User as the type of the generic parameter of the context: public class ApplicationDbContext : IdentityDbContext<WebAppIdentityDemoUser> //Update Startup.ConfigureServices to use the new {Application}User class, and finally generate migrations and synchronize the database. services.AddDefaultIdentity<WebAppIdentityDemoUser>() .AddDefaultUI() .AddEntityFrameworkStores<ApplicationDbContext>();
?2.2 Change the primary key type
Changing the data type of a PK column after the database has been created is problematic on many database systems. Changing the PK usually involves dropping and re-creating the table. Therefore, when creating the database, the PK type should be specified in the initial migration. Here are the steps to change the primary key type:
(1) To delete the database, the command is as follows:
Drop-Database
(2) Remove the previously generated migration, the command is as follows:
Remove-Migration
(3) Modify the user, role table primary key type, and related code changes
// user table set primary key to Int public class WebAppIdentityDemoUser : IdentityUser<int> { /// <summary> /// Full name /// </summary> [PersonalData] public string Name { get; set; } /// <summary> /// Birth Date /// </summary> [PersonalData] public DateTime DOB { get; set; } } // The role table sets the primary key to Int public class WebAppIdentityDemoRole : IdentityRole<int> { }
(4) Modify context
public class ApplicationDbContext : IdentityDbContext<WebAppIdentityDemoUser, WebAppIdentityDemoRole,int>
(5) Modify service registration
services.AddIdentity<WebAppIdentityDemoUser, WebAppIdentityDemoRole>() //If you use the Identity scaffolder to add the Identity file to the project, please delete the call AddDefaultUI to the project //.AddDefaultUI() .AddEntityFrameworkStores<ApplicationDbContext>() ?.AddDefaultTokenProviders();
(6) Generate the migration code, the command is as follows
Add-Migration IdentitySchema
(7) Synchronize database
Update-Database IdentitySchema
At this time, the primary key type of the table has been modified, including the foreign key type of the relational table, which has also been updated simultaneously, as shown in the following figure:
?2.3 Add navigation attributes
Navigation properties only exist in the EF model, not in the database. If the navigation relationship has not changed, the model change does not need to update the database. Changing the model configuration of a relationship can be more difficult than making other changes. Care must be taken to replace existing relationships. The following example does not change the model relationship, but only adds navigation properties to the user model and specifies the relationship in the context:
public class WebAppIdentityDemoUser : IdentityUser<int> { /// <summary> /// Full name /// </summary> [PersonalData] public string Name { get; set; } /// <summary> /// Birth Date /// </summary> [PersonalData] public DateTime DOB { get; set; } //Define navigation properties public virtual ICollection<IdentityUserClaim<int>> Claims { get; set; } }
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); builder.Entity<WebAppIdentityDemoUser>(b => { // Each User can have many UserClaims b.HasMany(e => e.Claims) .WithOne() .HasForeignKey(uc => uc.UserId) .IsRequired(); }); }
For all user navigation properties, user and role navigation properties, add all navigation properties. Refer to the official website documentation.
2.4 Change table/column name, field length (change in context)
protected override void OnModelCreating(ModelBuilder builder) { base.OnModelCreating(builder); //Change table name builder.Entity<IdentityUser>(b => { b.ToTable("MyUsers"); }); //Change table field name builder.Entity<IdentityUserClaim<string>>(b => { b.Property(e => e.ClaimType).HasColumnName("CType"); b.Property(e => e.ClaimValue).HasColumnName("CValue"); }); //change length builder.Entity<IdentityUser>(b => { b.Property(u => u.UserName).HasMaxLength(128); }); }
references
Custom Identity