首先聲明一下,我是按照下面的教程來進行操作的:
.NET 6 集成 IdentityServer4+AspNetCore Identity 讀取本地數據表用戶 - 董川民 (dongchuanmin.com)
具體步驟記錄如下:
一、新建空白項目
1、選擇Asp.net Core Api項目,如下圖
2、輸入項目名稱,如下圖:
3、選擇框架
二、添加引用的類庫
1、IdentityServer4
2、IdentityServer4.AspNetIdentity
3、Microsoft.EntityFrameworkCore
選擇6.0.12版本
4、Microsoft.AspNetCore.Identity.EntityFrameworkCore
選擇6.0.12版本
5、Microsoft.EntityFrameworkCore.Design
選擇6.0.12版本
6、Microsoft.EntityFrameworkCore.Tools
7、Pomelo.EntityFrameworkCore.MySql
8、NETCore.Encrypt【可以不用添加】
下面是安裝需要的類庫後的總體列表:
三、新建類庫:IdpConfig.cs
由於原作者沒有把api和client的配置放到數據庫裏,所以這裏是這樣配置的,代碼如下:
using IdentityServer4; using IdentityServer4.Models; namespace TestIdentityServer4InNetCore6 { public static class IdpConfig { public static IEnumerable<IdentityResource> GetIdentityResources() { return new IdentityResource[] { new IdentityResources.OpenId(), new IdentityResources.Profile(), new IdentityResources.Address(), new IdentityResources.Phone(), new IdentityResources.Email() }; } public static IEnumerable<ApiResource> GetApiResources() { return new[] { new ApiResource("api1", "My API #1") { Scopes = { "scope1"} } }; } public static IEnumerable<Client> GetClients() { return new[] { new Client { ClientId = "client", AllowedGrantTypes = GrantTypes.ResourceOwnerPassword, ClientSecrets = { new Secret("secret".Sha256()) }, AllowedScopes = //允許當訪問的資源 { "scope1", IdentityServerConstants.StandardScopes.OpenId, IdentityServerConstants.StandardScopes.Email, IdentityServerConstants.StandardScopes.Address, IdentityServerConstants.StandardScopes.Phone, IdentityServerConstants.StandardScopes.Profile } } }; } public static IEnumerable<ApiScope> GetScope() { return new ApiScope[] { new ApiScope("scope1"), new ApiScope("scope2"), }; } } }
四、新建類庫:ApplicationUser.cs
此類庫繼承於IdentityUser,可以在上面擴展自己需要的用戶的字段,代碼如下:
using Microsoft.AspNetCore.Identity; using System.ComponentModel; namespace TestIdentityServer4InNetCore6 { public class ApplicationUser : IdentityUser { public string MySomething { get; set; } = ""; /// <summary> /// 創建時間 /// </summary> public DateTime CreateTime { get; set; } /// <summary> /// 創建人Id /// </summary> public string CreatorId { get; set; } = ""; /// <summary> /// 否已刪除 /// </summary> public bool Deleted { get; set; } /// <summary> /// 姓名 /// </summary> public string RealName { get; set; } /// <summary> /// 性別 /// </summary> public Sex Sex { get; set; } /// <summary> /// 出生日期 /// </summary> public DateTime? Birthday { get; set; } /// <summary> /// 所屬部門Id /// </summary> public string DepartmentId { get; set; } = ""; public string OtherData { get; set; } = ""; // 用戶角色 用戶權限 用戶信息 用戶登錄tokens 重新綁定與父類的關係 命名必須和父類一致 public virtual ICollection<IdentityUserRole<string>> UserRoles { get; set; } public virtual ICollection<IdentityUserClaim<string>> Claims { get; set; } public virtual ICollection<IdentityUserLogin<string>> Logins { get; set; } public virtual ICollection<IdentityUserToken<string>> Tokens { get; set; } } public enum Sex { [Description("男")] Man = 1, [Description("女")] Woman = 0 } }
五、新建類庫:MyPasswordHasher.cs
此類是處理密碼加密和判斷的,代碼如下:
using Microsoft.AspNetCore.Identity; using NETCore.Encrypt.Extensions; namespace TestIdentityServer4InNetCore6 { public class MyPasswordHasher : PasswordHasher<ApplicationUser> { public override string HashPassword(ApplicationUser user, string password) { //PasswordHasher<ApplicationUser> ph = new PasswordHasher<ApplicationUser>(); //var pstr = ph.HashPassword(new ApplicationUser(), password); //return pstr; return password.MD5(); } public override PasswordVerificationResult VerifyHashedPassword(ApplicationUser user, string hashedPassword, string providedPassword) { if (providedPassword.MD5().Equals(hashedPassword)) { return PasswordVerificationResult.Success; } else { return PasswordVerificationResult.Failed; } } } }
六、新建類庫:IdpDbContext.cs
此類庫爲數據庫的上下文,在裏面初始化了角色和用戶和種子數據,主要是便於測試用,代碼如下:
using Microsoft.AspNetCore.Identity; using Microsoft.AspNetCore.Identity.EntityFrameworkCore; using Microsoft.EntityFrameworkCore; namespace TestIdentityServer4InNetCore6 { public class IdpDbContext : IdentityDbContext<ApplicationUser> { public IdpDbContext(DbContextOptions<IdpDbContext> opt) : base(opt) { } protected override void OnModelCreating(ModelBuilder builder) { base.OnModelCreating(builder); builder.Entity<ApplicationUser>().ToTable("ApplicationUsers"); MyPasswordHasher ph = new MyPasswordHasher(); #region 初始化用戶與角色的種子數據 //1. 更新用戶與角色的外鍵 builder.Entity<ApplicationUser>( u => u.HasMany(x => x.UserRoles).WithOne().HasForeignKey(ur => ur.UserId).IsRequired() ); //2. 添加管理員角色 var adminRoleId = "f8df1775-e889-46f4-acdd-421ec8d9ba64"; builder.Entity<IdentityRole>().HasData( new IdentityRole() { Id = adminRoleId, Name = "Admin", NormalizedName = "Admin".ToUpper() } ); //3. 添加用戶 var adminUserId = "f8df1775-e889-46f4-acdd-421ec8d9ba65"; ApplicationUser adminUser = new ApplicationUser { Id = adminUserId, UserName = "admin", NormalizedUserName = "admin".ToUpper(), RealName = "admin", NormalizedEmail = "[email protected]".ToUpper(), Email = "[email protected]", TwoFactorEnabled = false, EmailConfirmed = true, PhoneNumber = "123456789", PhoneNumberConfirmed = false, }; adminUser.PasswordHash = ph.HashPassword(adminUser, "123456"); builder.Entity<ApplicationUser>().HasData(adminUser); //4. 給用戶加入管理員角色 builder.Entity<IdentityUserRole<string>>().HasData( new IdentityUserRole<string>() { RoleId = adminRoleId, UserId = adminUserId } ); #endregion } } }
七、新建類庫:MyUserManager.cs
繼承於UserManager
using Microsoft.AspNetCore.Identity; using Microsoft.Extensions.Options; namespace TestIdentityServer4InNetCore6 { public class MyUserManager : UserManager<ApplicationUser> { public MyUserManager(IUserStore<ApplicationUser> store, IOptions<IdentityOptions> optionsAccessor, IPasswordHasher<ApplicationUser> passwordHasher, IEnumerable<IUserValidator<ApplicationUser>> userValidators, IEnumerable<IPasswordValidator<ApplicationUser>> passwordValidators, ILookupNormalizer keyNormalizer, IdentityErrorDescriber errors, IServiceProvider services, ILogger<UserManager<ApplicationUser>> logger) : base(store, optionsAccessor, new MyPasswordHasher(), userValidators, passwordValidators, keyNormalizer, errors, services, logger) { optionsAccessor.Value.Password.RequireDigit = false; optionsAccessor.Value.Password.RequiredLength = 4; optionsAccessor.Value.Password.RequireLowercase = false; optionsAccessor.Value.Password.RequireUppercase = false; optionsAccessor.Value.Password.RequireNonAlphanumeric = false; } } }
八、修改Program.cs類
主要是配置數據庫和identityserver4,數據庫連接字符串記得換成自己的,代碼如下:
using IdentityModel; using Microsoft.AspNetCore.Identity; using Microsoft.EntityFrameworkCore; using System.Security.Claims; using TestIdentityServer4InNetCore6; var builder = WebApplication.CreateBuilder(args); // Add services to the container. builder.Services.AddControllers(); // Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle builder.Services.AddEndpointsApiExplorer(); builder.Services.AddSwaggerGen(); builder.Services.AddDbContext<IdpDbContext>(opt => { opt.UseMySql("server=127.0.0.1;Port=3306;database=testidentityserver;uid=root;pwd=123456;", new MySqlServerVersion(new Version(8, 0, 29))); }); builder.Services.AddIdentity<ApplicationUser, IdentityRole>() .AddUserManager<MyUserManager>() .AddEntityFrameworkStores<IdpDbContext>() .AddDefaultTokenProviders(); builder.Services.AddIdentityServer() .AddDeveloperSigningCredential() .AddInMemoryIdentityResources(IdpConfig.GetIdentityResources()) .AddInMemoryClients(IdpConfig.GetClients()) .AddInMemoryApiScopes(IdpConfig.GetScope()) .AddInMemoryApiResources(IdpConfig.GetApiResources()) //.AddResourceOwnerValidator<MyResourceOwnerPasswordValidator>() //這句可以打開自主驗證登錄用戶 //.AddProfileService<MyProfileService>() .AddAspNetIdentity<ApplicationUser>(); var app = builder.Build(); // Configure the HTTP request pipeline. if (app.Environment.IsDevelopment()) { app.UseSwagger(); app.UseSwaggerUI(); } app.UseIdentityServer(); app.UseAuthorization(); app.MapControllers(); app.Run();
九、新建mysql空數據庫
數據庫的名稱爲:testidentityserver【跟第八步裏填寫的數據庫名稱要保持一致】
十、執行數據遷移
1、打開“程序包管理器控制檯”,輸入“Add-Migration CreateIdentitySchema”命令,代碼和截圖如下:
Add-Migration CreateIdentitySchema
2、恢復數據庫,輸入“Update-Database”,如下圖:
Update-Database
3、執行上一步的命令後,數據庫裏會自動創建如下表:
十、使用postman測試
1、啓動當前api項目,啓動成功後,界面如下:
2、使用postman調試
按照下圖的填寫參數,出現如下界面,表示運行成功