使用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,一些正常。

 

posted @ 2020-03-18 18:09  ZaraNet  阅读(1561)  评论(2编辑  收藏  举报