IdentityServer4(五):使用EF Core持久化配置和操作数据

使用Entity Framework Core持久化配置和操作数据

  • IdentityServer4.EntityFramework
  • 配置Stores
  • 添加数据库迁移
  • 播种数据

前文中,我们所有的IdentityServer4配置都是在代码中写死的,在实际的生产环境中肯定不能这么处理。本篇将使用Entity Framework Core持久化配置和存储操作数据。

IdentityServer4.EntityFramework

IdentityServer4.EntityFramework使用以下 DbContext 实现所需的存储和服务:

  • ConfigurationDbContext
    用于配置数据,如clients,resources和scopes。
  • PersistedGrantDbContext
    用于临时操作数据,如授权代码和刷新令牌

配置Stores

必要的nuget

Install-Package IdentityServer4.EntityFramework -Version 3.1.0
Install-Package Microsoft.EntityFrameworkCore.SqlServer -Version 3.1.0

我们在前文代码的基础上进行修改,删除了Config中写死的配置,添加了AddConfigurationStore()AddOperationalStore(),并使用SqlServer作为存储库。

public void ConfigureServices(IServiceCollection services)
{
    var connectionString = Configuration.GetConnectionString("DefaultConnection");
    var builder = services.AddIdentityServer()
        .AddConfigurationStore(options =>
        {
            options.ConfigureDbContext = builder =>
            {
                builder.UseSqlServer(connectionString);
            };
        })
        .AddOperationalStore(options =>
        {
            options.ConfigureDbContext = builder =>
            {
                builder.UseSqlServer(connectionString);
            };
        })
        .AddTestUsers(TestUsers.Users); ;
    builder.AddDeveloperSigningCredential();
    services.AddControllersWithViews();
}

appsettings.json中的配置

{
  "ConnectionStrings": {
    "DefaultConnection": "Server=localhost;Database=IDC;User ID=sa;Password=123456;"
  }
}

添加数据库迁移

执行迁移命令

add-migration InitialIdentityServerConfigurationDbMigration -c ConfigurationDbContext -o Data/Migrations/IdentityServer/ConfigurationDb
add-migration InitialIdentityServerPersistedGrantDbMigration -c PersistedGrantDbContext -o Data/Migrations/IdentityServer/PersistedGrantDb

可以看到,已成功将迁移代码保存到:~/Data/Migrations/IdentityServer
IdentityServer4(五):使用EF Core持久化配置和操作数据_第1张图片

播种数据

我们新建一个SeedData,提供一个public方法EnsureSeedData(),将我们此前写死在config中的配置信息持久化到SQL Server中。

public class SeedData
{
    public static void EnsureSeedData(string conncetionString)
    {
        var migtationAssembly = typeof(SeedData).GetTypeInfo().Assembly.GetName().Name;
        var service = new ServiceCollection();
        service.AddConfigurationDbContext(options =>
        {
            options.ConfigureDbContext = db => db.UseSqlServer(conncetionString, 
            	sql => sql.MigrationsAssembly(migtationAssembly));
        });
        service.AddOperationalDbContext(options =>
        {
            options.ConfigureDbContext = db => db.UseSqlServer(conncetionString, 
            	sql => sql.MigrationsAssembly(migtationAssembly));
        });

        var serviceProvider = service.BuildServiceProvider();

        using (var scope = serviceProvider.GetRequiredService<IServiceScopeFactory>().CreateScope())
        {
            scope.ServiceProvider.GetService<PersistedGrantDbContext>().Database.Migrate();

            var context = scope.ServiceProvider.GetService<ConfigurationDbContext>();
            context.Database.Migrate();
            EnsureSeedData(context);
        }
    }

    private static void EnsureSeedData(IConfigurationDbContext context)
    {
        if (!context.Clients.Any())
        {
            foreach (var client in Config.Clients)
                context.Clients.Add(client.ToEntity());
            context.SaveChanges();
        }
        if (!context.ApiResources.Any())
        {
            foreach (var api in Config.Apis)
                context.ApiResources.Add(api.ToEntity());
           context.SaveChanges();
        }

        if (!context.IdentityResources.Any())
        {
            foreach (var id in Config.Ids)
                context.IdentityResources.Add(id.ToEntity());
            context.SaveChanges();
        }
    }
}

在程序入口调用

public static void Main(string[] args)
{
    var host = CreateHostBuilder(args).Build();

    var config = host.Services.GetRequiredService<IConfiguration>();
    var connectionString = config.GetConnectionString("DefaultConnection");
    SeedData.EnsureSeedData(connectionString);
    
    host.Run();
}

当我们运行程序时,可以看到成功生成了数据库和相应的数据表
IdentityServer4(五):使用EF Core持久化配置和操作数据_第2张图片

配置信息也已经写入
IdentityServer4(五):使用EF Core持久化配置和操作数据_第3张图片

我们可以进行一次登录,然后查看PersistedGrants中的数据,可以看到
IdentityServer4(五):使用EF Core持久化配置和操作数据_第4张图片

你可能感兴趣的:(IdentityServer4)