使用Entity Framework Core持久化配置和操作數據
前文中,我們所有的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
播種數據
我們新建一個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();
}
當我們運行程序時,可以看到成功生成了數據庫和相應的數據表
配置信息也已經寫入
我們可以進行一次登錄,然後查看PersistedGrants
中的數據,可以看到