Skip to main content

使用EF Core支持的数据库来存储Identity Server4的配置

分类:  IdentityServer4教程 标签:  #Asp.Net core基础 #认证 #授权 #Identity Server #OpenId Connect #OAuth2 发布于: 2023-05-27 22:50:25

本节的源代码可以从如下位置找到:
sourcecode

我们前面的例子中在项目IdentityServer中都是使用一个config类来定义资源和scope, 以及客户端,但是在实际的应用中,我们可能需要更加方便的管理资源,scope以及客户端的形式,例如可以有一个界面允许客户端自己注册并生成security来使用QAuth2.0或者openIDConnect, 因此对于IdentityServer4来说我们需要一些其他的方法动态的配置这些参数。

IdentityServer4提供EF Core的支持,从而将这些配置放到数据库中进行保存。
EF Core的支持中分为两块,一块是对于配置的保存,另外一块是对一些中间运行的数据进行保存,例如生成的key等等。

IdentityServer4.EntityFramework

在is4中我们通过包IdentityServer4.EntityFramework来支持EF Core存储配置和运行数据的保存。
我们回到项目src\IdentityServer中, 运行如下的命令来添加包的支持:

dotnet add package IdentityServer4.EntityFramework
dotnet add package Microsoft.EntityFrameworkCore.SqlServer

注意
关于数据库的schema定义,您可以参考包IdentityServer4.EntityFramework.Storage, 你可以从这个脚本找到所有的数据库定义SQLScript

配置Store

请参考如下的代码:

src\IdentityServer\Startup.cs

            var migrationsAssembly = typeof(Startup).GetTypeInfo().Assembly.GetName().Name;
            const string connectionString = @"Data Source=(LocalDb)\MSSQLLocalDB;database=IdentityServer4.Quickstart.EntityFramework-4.0.0;trusted_connection=yes;";

            services.AddIdentityServer()
                .AddTestUsers(TestUsers.Users)
                .AddConfigurationStore(options =>
                {
                    options.ConfigureDbContext = b => b.UseSqlServer(connectionString,
                        sql => sql.MigrationsAssembly(migrationsAssembly));
                })
                .AddOperationalStore(options =>
                {
                    options.ConfigureDbContext = b => b.UseSqlServer(connectionString,
                        sql => sql.MigrationsAssembly(migrationsAssembly));
                })
                .AddDeveloperSigningCredential();

从这部分代码可以看出我们移除了之前的通过services.AddIentityServer().AddInMemoryIdentityResources(Config.IdentityResources) 将配置和中间的变量等放入了EF Core支持的数据库中。

注意
需要在类Startup.cs引入如下的包

using Microsoft.EntityFrameworkCore;
using System.Reflection;

添加数据库迁移

安装工具

dotnet tool install --global dotnet-ef
dotnet add package Microsoft.EntityFrameworkCore.Design

生成数据库迁移

dotnet ef migrations add InitialIdentityServerPersistedGrantDbMigration -c PersistedGrantDbContext -o Data/Migrations/IdentityServer/PersistedGrantDb
dotnet ef migrations add InitialIdentityServerConfigurationDbMigration -c ConfigurationDbContext -o Data/Migrations/IdentityServer/ConfigurationDb

初始化数据库

我们这里直接使用之前使用config.cs生成的数据,因此我们在这里定义一个初始化数据库的方法,改方法定义在类startup.cs中。

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.Clients)
            {
                context.Clients.Add(client.ToEntity());
            }
            context.SaveChanges();
        }

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

        if (!context.ApiScopes.Any())
        {
            foreach (var resource in Config.ApiScopes)
            {
                context.ApiScopes.Add(resource.ToEntity());
            }
            context.SaveChanges();
        }
    }
}

注意
我们需要在类Startup.cs中添加如下的引用

using System.Linq;
using IdentityServer4.EntityFramework.DbContexts;
using IdentityServer4.EntityFramework.Mappers;

然后在类Startup.Configure()中调用:

public void Configure(IApplicationBuilder app)
{
    // this will do the initial DB population
    InitializeDatabase(app);

    // the rest of the code that was already here
    // ...
}

然后运行之前的Api, IdentityServer以及JavaScriptClient应用进行测试就可以了