.Net6集成IdentityServer4 +AspNetCore Identity讀取數據表用戶且鑒權授權管理API
前言
IdentityServer4 實現鑒權、授權,AspNetCore Identity實現數據庫用戶管理表直接生成。
ps:IdentityServer4文檔上最後給的例子是 // 配置使用內存存儲用戶信息,但使用 EF 存儲客戶端和資源信息,
我初步要實現的是 //數據庫存儲用戶信息 內存存儲資源 (下一步資源也放數據庫 以後弄好瞭有機會更)
1.創建.Net6 API程序
一頓引用,包括
防止圖片掛掉打一遍文字:
- IdentityServer4、
- IdengtityServer4.AspNetIdentity、
- AspNetCore.Identity.EntityFrameWorkCore(生成數據庫表用的)、
- EntityFrameWork+Disign+Tool三件套 (缺瞭不能自動遷移)、
- Pomelo.EntityFrameWorkCore.MySql(我是用的MySql,如果是SqlServer 不用這個用一個大概叫EF.Sqlserver的)、
- Encrypt (加密MD5用的 不必須)、
下面那個是自帶的。
2.建立數據庫連接類
using Microsoft.AspNetCore.Identity; using Microsoft.EntityFrameworkCore; using MyIDP; using MyIDP.Models; using MyIDP.Permission; 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=AccountDb;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(MyIDP.IdpConfig.GetIdentityResources()) .AddInMemoryClients(MyIDP.IdpConfig.GetClients()) .AddInMemoryApiScopes( MyIDP.IdpConfig.GetScope()) .AddInMemoryApiResources( MyIDP.IdpConfig.GetApiResources()) //.AddResourceOwnerValidator<MyResourceOwnerPasswordValidator>() //這句可以打開自主驗證登錄用戶 //.AddProfileService<MyProfileService>() .AddAspNetIdentity<ApplicationUser>() //.AddTestUsers(new List<IdentityServer4.Test.TestUser> //{ // new IdentityServer4.Test.TestUser // { // SubjectId="123", // Username = "alice", // Password = "alice", // Claims = new List<Claim>() { // new Claim(JwtClaimTypes.Role, "superadmin"), // new Claim(JwtClaimTypes.Role, "admin") // } // } //}) ; 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();
3.Program裡開始加東西(如果是歷史的Net版本,是在StartUp裡)
using Microsoft.AspNetCore.Identity; using Microsoft.EntityFrameworkCore; using MyIDP; using MyIDP.Models; using MyIDP.Permission; 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=AccountDb;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(MyIDP.IdpConfig.GetIdentityResources()) .AddInMemoryClients(MyIDP.IdpConfig.GetClients()) .AddInMemoryApiScopes( MyIDP.IdpConfig.GetScope()) .AddInMemoryApiResources( MyIDP.IdpConfig.GetApiResources()) //.AddResourceOwnerValidator<MyResourceOwnerPasswordValidator>() //這句可以打開自主驗證登錄用戶 //.AddProfileService<MyProfileService>() .AddAspNetIdentity<ApplicationUser>() //.AddTestUsers(new List<IdentityServer4.Test.TestUser> //{ // new IdentityServer4.Test.TestUser // { // SubjectId="123", // Username = "alice", // Password = "alice", // Claims = new List<Claim>() { // new Claim(JwtClaimTypes.Role, "superadmin"), // new Claim(JwtClaimTypes.Role, "admin") // } // } //}) ; 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();
因為使用的是內存儲存t鑒權信息的方式,所以建立IdentityServer4的配置類IdpConfig
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 ApiResource[] //{ // new ApiResource("api1", "My API #1",new List<string>(){JwtClaimTypes.Role}) //}; //新寫法 return new[] { new ApiResource("api1", "My API #1") { Scopes = { "scope1"} } }; } public static IEnumerable<Client> GetClients() { return new[] { #region MyRegion //// client credentials flow client //new Client //{ // ClientId = "console client", // ClientName = "Client Credentials Client", // AllowedGrantTypes = GrantTypes.ClientCredentials, // ClientSecrets = { new Secret("511536EF-F270-4058-80CA-1C89C192F69A".Sha256()) }, // AllowedScopes = { "api1" } //}, #endregion // wpf client, password grant new Client { ClientId = "client", AllowedGrantTypes = GrantTypes.ResourceOwnerPassword, ClientSecrets = { new Secret("secret".Sha256()) }, AllowedScopes = //允許當訪問的資源 { "scope1", //"api1", 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"), }; } }
數據庫的usernamager
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; } }
重寫驗證密碼的方法類MyResourceOwnerPasswordValidator,(如果沒有打開Program中的AddResourceOwnerValidator<MyResourceOwnerPasswordValidator>() 則不需要)
public class MyResourceOwnerPasswordValidator : IResourceOwnerPasswordValidator { public readonly SignInManager<ApplicationUser> signInManager; private readonly MyUserManager userManager; //public readonly IEventService service; public MyResourceOwnerPasswordValidator(MyUserManager userService, SignInManager<ApplicationUser> signInManager)//, IEventService service) { userManager = userService; this.signInManager = signInManager; //this.service = service; } public async Task ValidateAsync(ResourceOwnerPasswordValidationContext context) { if (string.IsNullOrEmpty(context.UserName) || string.IsNullOrEmpty(context.Password)) { context.Result = new GrantValidationResult(TokenRequestErrors.InvalidGrant, "驗證被拒絕,用戶名或者密碼為空。"); return; } var user = await userManager.FindByNameAsync(context.UserName); if (user == null) { context.Result = new GrantValidationResult(TokenRequestErrors.InvalidGrant, "驗證失敗,不存在當前用戶。"); return; } //檢驗用戶密碼(雖然我也不知道他的密碼是采用什麼加密方式得到的,但是我也不需要知道) var passwordPass = await userManager.CheckPasswordAsync(user, context.Password); if (!passwordPass) { context.Result = new GrantValidationResult(TokenRequestErrors.InvalidGrant, "驗證失敗,用戶憑證錯誤"); return; } else { try { await userManager.AddLoginAsync(user, new UserLoginInfo(user.Id, "", user.UserName)); } catch (Exception ex) { ; } finally { context.Result = new GrantValidationResult(user.Id, GrantType.ResourceOwnerPassword, new List<Claim>() { new Claim("account", user.UserName) }); } } return; } }
MyPasswordHasher
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; } } }
創建自己的User類 ApplicationUser繼承 IdentityUser 復寫自帶的AspNetUser表
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 }
至此可以生成數據庫遷移後 Postman測試一下:
到此這篇關於.Net6集成IdentityServer4 +AspNetCore Identity讀取數據表用戶且鑒權授權管理API的文章就介紹到這瞭,更多相關.Net6 讀取數據表用戶內容請搜索WalkonNet以前的文章或繼續瀏覽下面的相關文章希望大傢以後多多支持WalkonNet!
推薦閱讀:
- .net core api接口JWT方式認證Token
- ASP.NET Core使用JWT自定義角色並實現策略授權需要的接口
- ASP.NET Core的中間件與管道介紹
- .NET Core配置連接字符串和獲取數據庫上下文實例
- ASP.NET Core 3.0輕量級角色API控制授權庫