哈嘍大家好,看見網上很少有使用MySql進行持久化的,畢竟又很多坑,說句實話,就連 MySql.Data.EntityFrameworkCore 都有問題,不知道是.net core更新太快還是其它的問題,但畢竟mssql驅動是沒問題的,感覺還是私心太大了。不得以之下選擇了一個第三方的驅動 Pomelo.EntityFrameworkCore.MySql 驅動,在這里主要是你安裝了它,你就又了它的設計器,但你還需要你安裝EFCore的設計器,因為你執行dotnet命令遷移的時候還得靠它,好吧,我們繼續,在你的應用程序中最好保持這幾個包。能多不能少。
<ItemGroup> <PackageReference Include="IdentityServer4" Version="2.0.0-rc1" /> <PackageReference Include="IdentityServer4.AspNetIdentity" Version="2.0.0-rc1" /> <PackageReference Include="IdentityServer4.EntityFramework" Version="2.0.0-rc1" /> <PackageReference Include="Microsoft.AspNetCore.All" Version="2.0.0" /> <PackageReference Include="Microsoft.EntityFrameworkCore" Version="2.0.0" /> <PackageReference Include="Microsoft.EntityFrameworkCore.Design" Version="2.0.0" /> <PackageReference Include="Microsoft.EntityFrameworkCore.Tools" Version="2.0.0" /> <PackageReference Include="Pomelo.EntityFrameworkCore.MySql" Version="2.0.0-rtm-10062" /> <PackageReference Include="Pomelo.EntityFrameworkCore.MySql.Design" Version="1.1.2" /> </ItemGroup>
就這樣,在Model里創建兩個類,一個是用戶、一個是關系,這個是Identity的類。其實這個和IdentityServer是沒有多大關系的。主要是為了擴展一些東西,比如你需要其它的字段?
public class ApplicationRole : IdentityRole{} public class ApplicationUser : IdentityUser{}
隨后我們定義IdentityDbContext,將我們自己定義的兩個類放進去,它是個泛型的。
public class ApplicationDbContext : IdentityDbContext<ApplicationUser, ApplicationRole, string> { public ApplicationDbContext(DbContextOptions<ApplicationDbContext> options) : base(options) { } protected override void OnModelCreating(ModelBuilder builder) { base.OnModelCreating(builder); // Customize the ASP.NET Identity model and override the defaults if needed. // For example, you can rename the ASP.NET Identity table names and more. // Add your customizations after calling base.OnModelCreating(builder); } }
再之后我們就可以注入到.Net Core的服務里了,IdentityServer的數據庫中有三個大類,有AspNet的票據用戶、資源的管理、以及一些操作的記錄。這里你可以用一個database,你也可以分開。
public void ConfigureServices(IServiceCollection services) { // Add framework services. services.AddDbContext<ApplicationDbContext>(options => options.UseMySql(Configuration.GetConnectionString("DefaultConnection"))); services.AddIdentity<ApplicationUser, ApplicationRole>() .AddEntityFrameworkStores<ApplicationDbContext>() .AddDefaultTokenProviders(); services.AddMvc(); string migrationsAssembly = typeof(Startup).GetTypeInfo().Assembly.GetName().Name; services.AddIdentityServer() .AddConfigurationStore(options => { options.ConfigureDbContext = builder => builder.UseMySql(Configuration.GetConnectionString("DefaultConnection"), sql => sql.MigrationsAssembly(migrationsAssembly)); }) .AddOperationalStore(options => { options.ConfigureDbContext = builder => builder.UseMySql(Configuration.GetConnectionString("DefaultConnection"), sql => sql.MigrationsAssembly(migrationsAssembly)); // this enables automatic token cleanup. this is optional. options.EnableTokenCleanup = true; options.TokenCleanupInterval = 30; }); }
隨后注冊IdentityServer服務,這個里面調用了 InitializeDatabase 方法為了初始化的遷移數據。
public void Configure(IApplicationBuilder app, IHostingEnvironment env) { InitializeDatabase(app); if (env.IsDevelopment()) app.UseDeveloperExceptionPage(); else app.UseExceptionHandler("/Home/Error"); app.UseIdentityServer(); }
這個方法就很有意思了,獲取了.net core的服務實例,然后對我的Context進行了更新遷移,直接將Config中的內存數據添加到了數據庫中。
private void InitializeDatabase(IApplicationBuilder app) { using (var serviceScope = app.ApplicationServices.GetService<IServiceScopeFactory>().CreateScope()) { serviceScope.ServiceProvider.GetRequiredService<ApplicationDbContext>().Database.Migrate(); 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 resource in Config.GetIdentityResources()) { context.IdentityResources.Add(resource.ToEntity()); } context.SaveChanges(); } if (!context.ApiResources.Any()) { foreach (var resource in Config.GetApiResources()) { context.ApiResources.Add(resource.ToEntity()); } context.SaveChanges(); } }
最后你需要執行三個命令,執行EFCore的數據遷移。
dotnet ef migrations add InitialIdentityServerPersistedGrantDbMigration -c PersistedGrantDbContext -o Data/Migrations/IdentityServer/PersistedGrantDb dotnet ef migrations add InitialIdentityServerConfigurationDbMigration -c ConfigurationDbContext -o Data/Migrations/IdentityServer/ConfigurationDb dotnet ef migrations add InitialIdentityServerApplicationDbMigration -c ApplicationDbContext -o Data/Migrations/IdentityServer/ApplicationDb
就這樣,生成完畢我們測試一下程序。
Ok,一些正常。