سفارشی کردن Identity Server4

سلام در مطلب قبلی نحوه سفارشی کردن UI یا همان رابط کاربری Identity Server گفتم: https://virgool.io/@espiar/%D8%B3%D9%81%D8%A7%D8%B1%D8%B4%DB%8C-%DA%A9%D8%B1%D8%AF%D9%86-identityserver4-ui-vyyncneeck6b در این مطلب می خواهم خود کلاس هاش را سفارشی کنیم. من فرض میکنم که شما یک پروژه Blazor Webassembly با Individual user account (که Authentication پیش فرض هست) ساختید.مرحله اول: ساخت ApiAuthorizationDbContext سفارشیاول از همه باید یک کلاس سفارشی DbContext بسازیم. من نام آن را CustomApiAuthorizationDbContext میگذارم. و کد زیر را درونش قرار میدهم:از اونجایی که ویرگول مثل همیشه با کد ها مشکل داره و این کد بسیار طولانی هست در تگ کد قرار نمیدهم!نکته مهمی که وجود دارد این هست که کدی که در منبع این مطلب هست ساده ترین کد است اما کدی که اینجا نوشتم کامل ترین حالت هست که باید هر 8 کلاس سفارشی بشود.شروع کدusing System;using System.Collections.Generic;using System.Text;using System.Threading.Tasks;using IdentityServer4.EntityFramework.Entities;using IdentityServer4.EntityFramework.Extensions;using IdentityServer4.EntityFramework.Interfaces;using IdentityServer4.EntityFramework.Options;using Microsoft.AspNetCore.Identity;using Microsoft.AspNetCore.Identity.EntityFrameworkCore;using Microsoft.EntityFrameworkCore;using Microsoft.Extensions.Options;namespace InfoFinder.Infrastructure.Data.Data{/// <summary>/// Database abstraction for a combined <see cref="DbContext"/> using ASP.NET Identity and Identity Server./// </summary>/// <typeparam name="TUser"></typeparam>/// <typeparam name="TRole"></typeparam>/// <typeparam name="TKey">Key of the IdentityUser entity</typeparam>public class KeyApiAuthorizationDbContext<TUser, TRole, TKey, TUserClaim, TUserRole, TUserLogin, TRoleClaim, TUserToken> : IdentityDbContext<TUser, TRole, TKey, TUserClaim, TUserRole, TUserLogin, TRoleClaim, TUserToken>, IPersistedGrantDbContextwhere TUser : IdentityUser<TKey>where TRole : IdentityRole<TKey>where TKey : IEquatable<TKey>where TUserClaim : IdentityUserClaim<TKey>where TUserRole : IdentityUserRole<TKey>where TUserLogin : IdentityUserLogin<TKey>where TRoleClaim : IdentityRoleClaim<TKey>where TUserToken : IdentityUserToken<TKey>{private readonly IOptions<OperationalStoreOptions> _operationalStoreOptions;/// <summary>/// Initializes a new instance of <see cref="ApiAuthorizationDbContext{TUser, TRole, TKey}"/>./// </summary>/// <param name="options">The <see cref="DbContextOptions"/>.</param>/// <param name="operationalStoreOptions">The <see cref="IOptions{OperationalStoreOptions}"/>.</param>public KeyApiAuthorizationDbContext(DbContextOptions options,IOptions<OperationalStoreOptions> operationalStoreOptions): base(options){_operationalStoreOptions = operationalStoreOptions;}/// <summary>/// Gets or sets the <see cref="DbSet{PersistedGrant}"/>./// </summary>public DbSet<PersistedGrant> PersistedGrants { get; set; }/// <summary>/// Gets or sets the <see cref="DbSet{DeviceFlowCodes}"/>./// </summary>public DbSet<DeviceFlowCodes> DeviceFlowCodes { get; set; }Task<int> IPersistedGrantDbContext.SaveChangesAsync() => base.SaveChangesAsync();/// <inheritdoc />protected override void OnModelCreating(ModelBuilder builder){base.OnModelCreating(builder);builder.ConfigurePersistedGrantContext(_operationalStoreOptions.Value);}}/// <summary>/// Database abstraction for a combined <see cref="DbContext"/> using ASP.NET Identity and Identity Server./// </summary>/// <typeparam name="TUser"></typeparam>public class ApiAuthorizationDbContext<TUser> : KeyApiAuthorizationDbContext<TUser, IdentityRole, string, IdentityUserClaim<string>, IdentityUserRole<string>, IdentityUserLogin<string>, IdentityRoleClaim<string>, IdentityUserToken<string>>where TUser : IdentityUser{/// <summary>/// Initializes a new instance of <see cref="ApiAuthorizationDbContext{TUser}"/>./// </summary>/// <param name="options">The <see cref="DbContextOptions"/>.</param>/// <param name="operationalStoreOptions">The <see cref="IOptions{OperationalStoreOptions}"/>.</param>public ApiAuthorizationDbContext(DbContextOptions options,IOptions<OperationalStoreOptions> operationalStoreOptions): base(options, operationalStoreOptions){}}}پایان کدمرحله دوم ساخت کلاس های سفارشیکلاس های زیر کلاس های سفارشی Identity معمولی می باشد:TUser, TRole, TKey, TUserClaim, TUserRole, TUserLogin, TRoleClaim, TUserTokenکه سفارشی کردنشو در پست پایین و منبع آمده (البته منبع کامل تر هست) https://virgool.io/@espiar/%D8%B3%D9%81%D8%A7%D8%B1%D8%B4%DB%8C-%DA%A9%D8%B1%D8%AF%D9%86-identity-%D8%AF%D8%B1-dotnetcore31-idbh9ahawqvh مرحله سوم جایگزین کردن Context سفارشی که در مرحله اول ساختیم بجای Context پیشفرضبعد باید dbContext سفارشی خودمان را جایگزین dbContext پیش فرض کنیم و 8 کلاس سفارشی هم به آن پاس بدیهم:مرحله چهارم تغییر فایل Startupحالا باید کلاس های سفارشی را در فایل Stratup به Identity پاس دهیم:کلاس های ApplicationUser و ApplicationRole سفارشی من هستند که به Services.AddDefaultIdentity پاس دادمتنها خطی که فایل startup اضافه شد کد زیر هست:.AddRoles<ApplicationRole>()باقس کد بطور پیشفرض وجود دارد فقط باید نام کلاس سفارشی جایگزین کنید.نکته: نام کلاس سفارشی user من ApplicationUser هست. که بطور پیشفرض این کلاس سفارشی (و البته خالی) وجود دارد.و مرحله پنجم و آخرابتدا Migration ها رو پاک می کنیم و بعد اگر دیتابیس ساخته شده آن هم پاک میکنیم.و دستورات زیر را میزنیم:Add-Migration MigrationNameUpdate-Databaseدستورات بالا که پرواضح و برای EntityFramework هست. این دستورات باید بدون خطا انجام شوند در غیر این صورت جاییرو مثل این مطلب پیش نرفتید.منابع: https://stackoverflow.com/questions/58208894/aspnet-core-identity-custom-apiauthorizationdbcontext و https://docs.microsoft.com/en-us/aspnet/core/security/authentication/customize-identity-model?view=aspnetcore-3.1#customize-the-model