使用MySql對IdentityServer4進行持久化


  哈嘍大家好,看見網上很少有使用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,一些正常。

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM