<十一>将identityserver4的一些权限配置持久化到数据库
刚开始为了方便,我们把配置写在一个config的类里面了,用内存加载的方式加载进去。
下面我们把这些配置持久化到数据库。
引入 IDentityserver4.EntityFrameWork 的nuget包。
然后修改部分startup的部分配置。
public void ConfigureServices(IServiceCollection services) { string connectionstring = Configuration.GetConnectionString("IdentityServer4Conn"); var migrationsAssembly= typeof(Startup).Assembly.GetName().Name; services.Configure<CookiePolicyOptions>(options => { // This lambda determines whether user consent for non-essential cookies is needed for a given request. options.CheckConsentNeeded = context => true; options.MinimumSameSitePolicy = SameSiteMode.None; }); services.AddDbContext<ApplicationDbContext>(options => { options.UseSqlServer(Configuration.GetConnectionString("IdentityConn")); }); //配置Identity services.AddIdentity<ApplicationUser, ApplicationUserRoles>() .AddEntityFrameworkStores<ApplicationDbContext>() .AddDefaultTokenProviders(); //修改Identity密码强度设置配置 services.Configure<IdentityOptions>(options => { options.Password.RequireLowercase = false; //需要小写 options.Password.RequireNonAlphanumeric = false; //需要字母 options.Password.RequireUppercase = false; //需要大写 options.Password.RequiredLength = 6; }); //IdentityServer4.EntityFramework.DbContexts.ConfigurationDbContext // IdentityServer4.EntityFramework.DbContexts.PersistedGrantDbContext services.AddIdentityServer().AddDeveloperSigningCredential() // .AddInMemoryApiResources(Config.GetApiResources()) // .AddInMemoryApiScopes(Config.GetScopes()) // .AddInMemoryClients(Config.GetClients()) // .AddTestUsers(Config.GetUsers().ToList()) .AddAspNetIdentity<ApplicationUser>() // .AddInMemoryIdentityResources(Config.GetIdentityResources()) //添加client配置 .AddConfigurationStore(options => { options.ConfigureDbContext = builder => { builder.UseSqlServer(connectionstring, sql => sql.MigrationsAssembly(migrationsAssembly)); }; }) // this adds the operational data from DB (codes, tokens, consents) //添加resource scopes等配置 .AddOperationalStore(options => { options.ConfigureDbContext = b => b.UseSqlServer(connectionstring, sql => sql.MigrationsAssembly(migrationsAssembly)); // this enables automatic token cleanup. this is optional. options.EnableTokenCleanup = true; }); services.AddControllersWithViews(); }
appsetting.json中添加新的数据库链接配置
"ConnectionStrings": { "IdentityConn": "Data Source=127.0.0.1;User ID=sa;Password=62;database=IdentityTest;Connect Timeout=30;Encrypt=False;TrustServerCertificate=False;ApplicationIntent=ReadWrite;MultiSubnetFailover=False", "IdentityServer4Conn": "Data Source=127.0.0.1;User ID=sa;Password=62;database=IdentityServer4Test;Connect Timeout=30;Encrypt=False;TrustServerCertificate=False;ApplicationIntent=ReadWrite;MultiSubnetFailover=False" }
配置完成后用add-migration 命令试一下,发生如下错误
说要使用指定的Dbcontext,IdentityServer4.EntityFrameWork里面有两个context需要我们初始化
IdentityServer4.EntityFramework.DbContexts.ConfigurationDbContext
IdentityServer4.EntityFramework.DbContexts.PersistedGrantDbContext
由于上次我们给Identity 做过持久化,那么migration的存放位置需要就不能用Data了,我们给指定在Data下面的自文件夹下,命令如下
add-migration init -Context ConfigurationDbContext -OutputDir Data/Migrations/IdentityServer4/configurationDbContext add-migration init -Context PersistedGrantDbContext -OutputDir Data/Migrations/IdentityServer4/persistedGrantDbContext
update-database -Context ConfigurationDbContext
update-database -Context PersistedGrantDbContext
看下生成的migration的放置位置和数据库生成的表
这样 持久化就完成了,那么我们尝试着来给数据表初始化一些数据。
利用Identityserver4.EntityframeWork.Mapper 这个映射工具,将我们在config中的配置映射并初始化到数据库中去,在startup中的configure函数中运行此方法。
public void Configure(IApplicationBuilder app, IHostingEnvironment env) { if (env.IsDevelopment()) { app.UseDeveloperExceptionPage(); } else { app.UseExceptionHandler("/Home/Error"); } InitializeDatabase(app); app.UseStaticFiles(); app.UseCookiePolicy(); app.UseIdentityServer(); app.UseMvc(routes => { routes.MapRoute( name: "default", template: "{controller=Home}/{action=Index}/{id?}"); }); }
private void InitializeDatabase(IApplicationBuilder app) { using (var serviceScope = app.ApplicationServices.GetService<IServiceScopeFactory>().CreateScope()) { serviceScope.ServiceProvider.GetRequiredService<PersistedGrantDbContext>().Database.Migrate(); var context = serviceScope.ServiceProvider.GetRequiredService<ConfigurationDbContext>(); context.Database.Migrate(); if (!context.Clients.Any()) { foreach (var client in Config.GetClients()) { context.Clients.Add(client.ToEntity()); } context.SaveChanges(); } if (!context.IdentityResources.Any()) { foreach (var identityResource in Config.GetIdentityResources()) { context.IdentityResources.Add(identityResource.ToEntity()); } context.SaveChanges(); } if (!context.ApiResources.Any()) { foreach (var apiResource in Config.GetApiResources()) { context.ApiResources.Add(apiResource.ToEntity()); } context.SaveChanges(); } if (!context.ApiScopes.Any()) { foreach (var scope in Config.GetScopes()) { context.ApiScopes.Add(scope.ToEntity()); } context.SaveChanges(); } } }
开启服务端和客户端,将登陆逻辑走一遍,走通就可以了。